home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / ops.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-19  |  130.3 KB  |  5,437 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
  12.  *      op_change, op_yank, do_put, do_join
  13.  */
  14.  
  15. #include "vim.h"
  16.  
  17. /*
  18.  * Number of registers.
  19.  *    0 = unnamed register, for normal yanks and puts
  20.  *   1..9 = registers '1' to '9', for deletes
  21.  * 10..35 = registers 'a' to 'z'
  22.  *     36 = delete register '-'
  23.  *     37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
  24.  *     38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
  25.  */
  26. /*
  27.  * Symbolic names for some registers.
  28.  */
  29. #define DELETION_REGISTER    36
  30. #ifdef FEAT_CLIPBOARD
  31. # define STAR_REGISTER        37
  32. #  ifdef FEAT_X11
  33. #   define PLUS_REGISTER    38
  34. #  else
  35. #   define PLUS_REGISTER    STAR_REGISTER        /* there is only one */
  36. #  endif
  37. #endif
  38.  
  39. #ifdef FEAT_CLIPBOARD
  40. # define NUM_REGISTERS        (PLUS_REGISTER + 1)
  41. #else
  42. # define NUM_REGISTERS        37
  43. #endif
  44.  
  45. /*
  46.  * Each yank register is an array of pointers to lines.
  47.  */
  48. static struct yankreg
  49. {
  50.     char_u    **y_array;    /* pointer to array of line pointers */
  51.     linenr_T    y_size;        /* number of lines in y_array */
  52.     char_u    y_type;        /* MLINE, MCHAR or MBLOCK */
  53.     colnr_T    y_width;    /* only set if y_type == MBLOCK */
  54. } y_regs[NUM_REGISTERS];
  55.  
  56. static struct yankreg    *y_current;        /* ptr to current yankreg */
  57. static int        y_append;        /* TRUE when appending */
  58. static struct yankreg    *y_previous = NULL; /* ptr to last written yankreg */
  59.  
  60. /*
  61.  * structure used by block_prep, op_delete and op_yank for blockwise operators
  62.  * also op_change, op_shift, op_insert, op_replace - AKelly
  63.  */
  64. struct block_def
  65. {
  66.     int        startspaces;    /* 'extra' cols of first char */
  67.     int        endspaces;    /* 'extra' cols of first char */
  68.     int        textlen;    /* chars in block */
  69.     char_u    *textstart;    /* pointer to 1st char in block */
  70.     colnr_T    textcol;    /* cols of chars (at least part.) in block */
  71.     colnr_T    start_vcol;    /* start col of 1st char wholly inside block */
  72.     colnr_T    end_vcol;    /* start col of 1st char wholly after block */
  73. #ifdef FEAT_VISUALEXTRA
  74.     int        is_short;    /* TRUE if line is too short to fit in block */
  75.     int        is_MAX;        /* TRUE if curswant==MAXCOL when starting */
  76.     int        is_oneChar;    /* TRUE if block within one character */
  77.     int        pre_whitesp;    /* screen cols of ws before block */
  78.     int        pre_whitesp_c;    /* chars of ws before block */
  79.     colnr_T    end_char_vcols;    /* number of vcols of post-block char */
  80. #endif
  81.     colnr_T    start_char_vcols; /* number of vcols of pre-block char */
  82. };
  83.  
  84. #ifdef FEAT_VISUALEXTRA
  85. static void shift_block __ARGS((oparg_T *oap, int amount));
  86. static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp));
  87. #endif
  88. #ifdef FEAT_EVAL
  89. static char_u    *get_expr_line __ARGS((void));
  90. #endif
  91. static void    get_yank_register __ARGS((int regname, int writing));
  92. static int    stuff_yank __ARGS((int, char_u *));
  93. static int    put_in_typebuf __ARGS((char_u *s, int colon));
  94. static void    stuffescaped __ARGS((char_u *arg, int literally));
  95. static int    get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg));
  96. static void    cmdline_paste_str __ARGS((char_u *s, int literally));
  97. #ifdef FEAT_MBYTE
  98. static void    mb_adjust_opend __ARGS((oparg_T *oap));
  99. #endif
  100. static void    free_yank __ARGS((long));
  101. static void    free_yank_all __ARGS((void));
  102. #ifdef FEAT_CLIPBOARD
  103. static void    copy_yank_reg __ARGS((struct yankreg *reg));
  104. #endif
  105. static void    block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
  106. #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
  107. static void    str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len));
  108. #endif
  109. #ifdef FEAT_COMMENTS
  110. static int    same_leader __ARGS((int, char_u *, int, char_u *));
  111. static int    fmt_check_par __ARGS((linenr_T, int *, char_u **, int do_comments));
  112. #else
  113. static int    fmt_check_par __ARGS((linenr_T));
  114. #endif
  115.  
  116. /*
  117.  * The names of operators.
  118.  * IMPORTANT: Index must correspond with defines in vim.h!!!
  119.  * The third field indicates whether the operator always works on lines.
  120.  */
  121. static char opchars[][3] =
  122. {
  123.     {NUL, NUL, FALSE},    /* OP_NOP */
  124.     {'d', NUL, FALSE},    /* OP_DELETE */
  125.     {'y', NUL, FALSE},    /* OP_YANK */
  126.     {'c', NUL, FALSE},    /* OP_CHANGE */
  127.     {'<', NUL, TRUE},    /* OP_LSHIFT */
  128.     {'>', NUL, TRUE},    /* OP_RSHIFT */
  129.     {'!', NUL, TRUE},    /* OP_FILTER */
  130.     {'g', '~', FALSE},    /* OP_TILDE */
  131.     {'=', NUL, TRUE},    /* OP_INDENT */
  132.     {'g', 'q', TRUE},    /* OP_FORMAT */
  133.     {':', NUL, TRUE},    /* OP_COLON */
  134.     {'g', 'U', FALSE},    /* OP_UPPER */
  135.     {'g', 'u', FALSE},    /* OP_LOWER */
  136.     {'J', NUL, TRUE},    /* DO_JOIN */
  137.     {'g', 'J', TRUE},    /* DO_JOIN_NS */
  138.     {'g', '?', FALSE},    /* OP_ROT13 */
  139.     {'r', NUL, FALSE},    /* OP_REPLACE */
  140.     {'I', NUL, FALSE},    /* OP_INSERT */
  141.     {'A', NUL, FALSE},    /* OP_APPEND */
  142.     {'z', 'f', TRUE},    /* OP_FOLD */
  143.     {'z', 'o', TRUE},    /* OP_FOLDOPEN */
  144.     {'z', 'O', TRUE},    /* OP_FOLDOPENREC */
  145.     {'z', 'c', TRUE},    /* OP_FOLDCLOSE */
  146.     {'z', 'C', TRUE},    /* OP_FOLDCLOSEREC */
  147.     {'z', 'd', TRUE},    /* OP_FOLDDEL */
  148.     {'z', 'D', TRUE},    /* OP_FOLDDELREC */
  149. };
  150.  
  151. /*
  152.  * Translate a command name into an operator type.
  153.  * Must only be called with a valid operator name!
  154.  */
  155.     int
  156. get_op_type(char1, char2)
  157.     int        char1;
  158.     int        char2;
  159. {
  160.     int        i;
  161.  
  162.     if (char1 == 'r')        /* ignore second character */
  163.     return OP_REPLACE;
  164.     if (char1 == '~')        /* when tilde is an operator */
  165.     return OP_TILDE;
  166.     for (i = 0; ; ++i)
  167.     if (opchars[i][0] == char1 && opchars[i][1] == char2)
  168.         break;
  169.     return i;
  170. }
  171.  
  172. #if defined(FEAT_VISUAL) || defined(PROTO)
  173. /*
  174.  * Return TRUE if operator "op" always works on whole lines.
  175.  */
  176.     int
  177. op_on_lines(op)
  178.     int op;
  179. {
  180.     return opchars[op][2];
  181. }
  182. #endif
  183.  
  184. /*
  185.  * Get first operator command character.
  186.  * Returns 'g' or 'z' if there is another command character.
  187.  */
  188.     int
  189. get_op_char(optype)
  190.     int        optype;
  191. {
  192.     return opchars[optype][0];
  193. }
  194.  
  195. /*
  196.  * Get second operator command character.
  197.  */
  198.     int
  199. get_extra_op_char(optype)
  200.     int        optype;
  201. {
  202.     return opchars[optype][1];
  203. }
  204.  
  205. /*
  206.  * op_shift - handle a shift operation
  207.  */
  208.     void
  209. op_shift(oap, curs_top, amount)
  210.     oparg_T        *oap;
  211.     int            curs_top;
  212.     int            amount;
  213. {
  214.     long        i;
  215.     int            first_char;
  216.     int            block_col = 0;
  217.     char_u        *s;
  218.  
  219.     if (u_save((linenr_T)(oap->start.lnum - 1),
  220.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  221.     return;
  222.  
  223.     if (oap->block_mode)
  224.     block_col = curwin->w_cursor.col;
  225.  
  226.     for (i = oap->line_count; --i >= 0; )
  227.     {
  228.     first_char = *ml_get_curline();
  229.     if (first_char == NUL)                /* empty line */
  230.         curwin->w_cursor.col = 0;
  231. #ifdef FEAT_VISUALEXTRA
  232.     else if (oap->block_mode)
  233.         shift_block(oap, amount);
  234. #endif
  235.     else
  236.         /* Move the line right if it doesn't start with '#', 'smartindent'
  237.          * isn't set or 'cindent' isn't set or '#' isn't in 'cino'. */
  238. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
  239.         if (first_char != '#' || !preprocs_left())
  240. #endif
  241.     {
  242.         shift_line(oap->op_type == OP_LSHIFT, p_sr, amount);
  243.     }
  244.     ++curwin->w_cursor.lnum;
  245.     }
  246.  
  247.     changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
  248.  
  249.     if (oap->block_mode)
  250.     {
  251.     curwin->w_cursor.lnum = oap->start.lnum;
  252.     curwin->w_cursor.col = block_col;
  253.     }
  254.     else if (curs_top)        /* put cursor on first line, for ">>" */
  255.     {
  256.     curwin->w_cursor.lnum = oap->start.lnum;
  257.     beginline(BL_SOL | BL_FIX);   /* shift_line() may have set cursor.col */
  258.     }
  259.     else
  260.     --curwin->w_cursor.lnum;    /* put cursor on last line, for ":>" */
  261.  
  262.     if (oap->line_count > p_report)
  263.     {
  264.     if (oap->op_type == OP_RSHIFT)
  265.         s = (char_u *)">";
  266.     else
  267.         s = (char_u *)"<";
  268.     if (oap->line_count == 1)
  269.     {
  270.         if (amount == 1)
  271.         sprintf((char *)IObuff, _("1 line %sed 1 time"), s);
  272.         else
  273.         sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount);
  274.     }
  275.     else
  276.     {
  277.         if (amount == 1)
  278.         sprintf((char *)IObuff, _("%ld lines %sed 1 time"),
  279.                               oap->line_count, s);
  280.         else
  281.         sprintf((char *)IObuff, _("%ld lines %sed %d times"),
  282.                           oap->line_count, s, amount);
  283.     }
  284.     msg(IObuff);
  285.     }
  286.  
  287.     /*
  288.      * Set "'[" and "']" marks.
  289.      */
  290.     curbuf->b_op_start = oap->start;
  291.     curbuf->b_op_end.lnum = oap->end.lnum;
  292.     curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  293.     if (curbuf->b_op_end.col > 0)
  294.     --curbuf->b_op_end.col;
  295. }
  296.  
  297. /*
  298.  * shift the current line one shiftwidth left (if left != 0) or right
  299.  * leaves cursor on first blank in the line
  300.  */
  301.     void
  302. shift_line(left, round, amount)
  303.     int    left;
  304.     int    round;
  305.     int    amount;
  306. {
  307.     int        count;
  308.     int        i, j;
  309.     int        p_sw = (int)curbuf->b_p_sw;
  310.  
  311.     count = get_indent();    /* get current indent */
  312.  
  313.     if (round)            /* round off indent */
  314.     {
  315.     i = count / p_sw;    /* number of p_sw rounded down */
  316.     j = count % p_sw;    /* extra spaces */
  317.     if (j && left)        /* first remove extra spaces */
  318.         --amount;
  319.     if (left)
  320.     {
  321.         i -= amount;
  322.         if (i < 0)
  323.         i = 0;
  324.     }
  325.     else
  326.         i += amount;
  327.     count = i * p_sw;
  328.     }
  329.     else        /* original vi indent */
  330.     {
  331.     if (left)
  332.     {
  333.         count -= p_sw * amount;
  334.         if (count < 0)
  335.         count = 0;
  336.     }
  337.     else
  338.         count += p_sw * amount;
  339.     }
  340.  
  341.     /* Set new indent */
  342. #ifdef FEAT_VREPLACE
  343.     if (State & VREPLACE_FLAG)
  344.     change_indent(INDENT_SET, count, FALSE, NUL);
  345.     else
  346. #endif
  347.     (void)set_indent(count, SIN_CHANGED);
  348. }
  349.  
  350. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  351. /*
  352.  * Shift one line of the current block one shiftwidth right or left.
  353.  * Leaves cursor on first character in block.
  354.  */
  355.     static void
  356. shift_block(oap, amount)
  357.     oparg_T    *oap;
  358.     int        amount;
  359. {
  360.     int            left = (oap->op_type == OP_LSHIFT);
  361.     int            oldstate = State;
  362.     int            total, split;
  363.     char_u        *newp, *oldp, *midp, *ptr;
  364.     int            oldcol = curwin->w_cursor.col;
  365.     int            p_sw = (int)curbuf->b_p_sw;
  366.     int            p_ts = (int)curbuf->b_p_ts;
  367.     struct block_def    bd;
  368.     int            internal = 0;
  369.     int            incr;
  370.     colnr_T        vcol, col = 0, ws_vcol;
  371.     int            i = 0, j = 0;
  372.     int            len;
  373.  
  374. #ifdef FEAT_RIGHTLEFT
  375.     int            old_p_ri = p_ri;
  376.  
  377.     p_ri = 0;            /* don't want revins in ident */
  378. #endif
  379.  
  380.     State = INSERT;        /* don't want REPLACE for State */
  381.     block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
  382.     if (bd.is_short)
  383.     return;
  384.  
  385.     /* total is number of screen columns to be inserted/removed */
  386.     total = amount * p_sw;
  387.     oldp = ml_get_curline();
  388.  
  389.     if (!left)
  390.     {
  391.     /*
  392.      *  1. Get start vcol
  393.      *  2. Total ws vcols
  394.      *  3. Divvy into TABs & spp
  395.      *  4. Construct new string
  396.      */
  397.     total += bd.pre_whitesp; /* all virtual WS upto & incl a split TAB */
  398.     ws_vcol = bd.start_vcol - bd.pre_whitesp;
  399.     if (bd.startspaces)
  400.     {
  401. #ifdef FEAT_MBYTE
  402.         if (has_mbyte)
  403.         bd.textstart += (*mb_ptr2len_check)(bd.textstart);
  404. #endif
  405.         ++bd.textstart;
  406.     }
  407.     for ( ; vim_iswhite(*bd.textstart); )
  408.     {
  409.         incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol));
  410.         total += incr;
  411.         bd.start_vcol += incr;
  412.     }
  413.     /* OK, now total=all the VWS reqd, and textstart points at the 1st
  414.      * non-ws char in the block. */
  415.     if (!curbuf->b_p_et)
  416.         i = ((ws_vcol % p_ts) + total) / p_ts; /* number of tabs */
  417.     if (i)
  418.         j = ((ws_vcol % p_ts) + total) % p_ts; /* number of spp */
  419.     else
  420.         j = total;
  421.     /* if we're splitting a TAB, allow for it */
  422.     bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
  423.     len = (int)STRLEN(bd.textstart) + 1;
  424.     newp = alloc_check((unsigned)(bd.textcol + i + j + len));
  425.     if (newp == NULL)
  426.         return;
  427.     vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
  428.     mch_memmove(newp, oldp, (size_t)bd.textcol);
  429.     copy_chars(newp + bd.textcol, (size_t)i, TAB);
  430.     copy_spaces(newp + bd.textcol + i, (size_t)j);
  431.     /* the end */
  432.     mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len);
  433.     }
  434.     else /* left */
  435.     {
  436.     vcol = oap->start_vcol;
  437.     /* walk vcol past ws to be removed */
  438.     for (midp = oldp + bd.textcol;
  439.           vcol < (oap->start_vcol + total) && vim_iswhite(*midp); )
  440.     {
  441.         incr = lbr_chartabsize_adv(&midp, (colnr_T)vcol);
  442.         vcol += incr;
  443.     }
  444.     /* internal is the block-internal ws replacing a split TAB */
  445.     if (vcol > (oap->start_vcol + total))
  446.     {
  447.         /* we have to split the TAB *(midp-1) */
  448.         internal = vcol - (oap->start_vcol + total);
  449.     }
  450.     /* if 'expandtab' is not set, use TABs */
  451.  
  452.     split = bd.startspaces + internal;
  453.     if (split > 0)
  454.     {
  455.         if (!curbuf->b_p_et)
  456.         {
  457.         for (ptr = oldp, col = 0; ptr < oldp+bd.textcol; )
  458.             col += lbr_chartabsize_adv(&ptr, (colnr_T)col);
  459.  
  460.         /* col+1 now equals the start col of the first char of the
  461.          * block (may be < oap.start_vcol if we're splitting a TAB) */
  462.         i = ((col % p_ts) + split) / p_ts; /* number of tabs */
  463.         }
  464.         if (i)
  465.         j = ((col % p_ts) + split) % p_ts; /* number of spp */
  466.         else
  467.         j = split;
  468.     }
  469.  
  470.     newp = alloc_check(bd.textcol + i + j + (unsigned)STRLEN(midp) + 1);
  471.     if (newp == NULL)
  472.         return;
  473.     vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + STRLEN(midp) + 1));
  474.  
  475.     /* copy first part we want to keep */
  476.     mch_memmove(newp, oldp, (size_t)bd.textcol);
  477.     /* Now copy any TABS and spp to ensure correct alignment! */
  478.     while (vim_iswhite(*midp))
  479.     {
  480.         if (*midp == TAB)
  481.         i++;
  482.         else /*space */
  483.         j++;
  484.         midp++;
  485.     }
  486.     /* We might have an extra TAB worth of spp now! */
  487.     if (j / p_ts && !curbuf->b_p_et)
  488.     {
  489.         i++;
  490.         j -= p_ts;
  491.     }
  492.     copy_chars(newp + bd.textcol, (size_t)i, TAB);
  493.     copy_spaces(newp + bd.textcol + i, (size_t)j);
  494.  
  495.     /* the end */
  496.     mch_memmove(newp + STRLEN(newp), midp, (size_t)STRLEN(midp) + 1);
  497.     }
  498.     /* replace the line */
  499.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  500.     changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol);
  501.     State = oldstate;
  502.     curwin->w_cursor.col = oldcol;
  503. #ifdef FEAT_RIGHTLEFT
  504.     p_ri = old_p_ri;
  505. #endif
  506. }
  507. #endif
  508.  
  509. #ifdef FEAT_VISUALEXTRA
  510. /*
  511.  * Insert string "s" (b_insert ? before : after) block :AKelly
  512.  */
  513.     static void
  514. block_insert(oap, s, b_insert, bdp)
  515.     oparg_T        *oap;
  516.     char_u        *s;
  517.     int            b_insert;
  518.     struct block_def    *bdp;
  519. {
  520.     int        p_ts;
  521.     int        count = 0;    /* extra spaces to replace a cut TAB */
  522.     int        spaces = 0;    /* non-zero if cutting a TAB */
  523.     colnr_T    offset;        /* pointer along new line */
  524.     unsigned    s_len;        /* STRLEN(s) */
  525.     char_u    *newp, *oldp;    /* new, old lines */
  526.     linenr_T    lnum;        /* loop var */
  527.     int        oldstate = State;
  528.  
  529.     State = INSERT;        /* don't want REPLACE for State */
  530.     s_len = (unsigned)STRLEN(s);
  531.  
  532.     for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++)
  533.     {
  534.     block_prep(oap, bdp, lnum, TRUE);
  535.     if (bdp->is_short && b_insert)
  536.         continue;    /* OP_INSERT, line ends before block start */
  537.  
  538.     oldp = ml_get(lnum);
  539.  
  540.     if (b_insert)
  541.     {
  542.         p_ts = bdp->start_char_vcols;
  543.         spaces = bdp->startspaces;
  544.         if (spaces != 0)
  545.         count = p_ts - 1; /* we're cutting a TAB */
  546.         offset = bdp->textcol;
  547.     }
  548.     else /* append */
  549.     {
  550.         p_ts = bdp->end_char_vcols;
  551.         if (!bdp->is_short) /* spaces = padding after block */
  552.         {
  553.         spaces = (bdp->endspaces ? p_ts - bdp->endspaces : 0);
  554.         if (spaces != 0)
  555.             count = p_ts - 1; /* we're cutting a TAB */
  556.         offset = bdp->textcol + bdp->textlen - (spaces != 0);
  557.         }
  558.         else /* spaces = padding to block edge */
  559.         {
  560.         /* if $ used, just append to EOL (ie spaces==0) */
  561.         if (!bdp->is_MAX)
  562.             spaces = (oap->end_vcol - bdp->end_vcol) + 1;
  563.         count = spaces;
  564.         offset = bdp->textcol + bdp->textlen;
  565.         }
  566.     }
  567.  
  568.     newp = alloc_check((unsigned)(STRLEN(oldp)) + s_len + count + 1);
  569.     if (newp == NULL)
  570.         continue;
  571.  
  572.     /* copy up to shifted part */
  573.     mch_memmove(newp, oldp, (size_t)(offset));
  574.     oldp += offset;
  575.  
  576.     /* insert pre-padding */
  577.     copy_spaces(newp + offset, (size_t)spaces);
  578.  
  579.     /* copy the new text */
  580.     mch_memmove(newp + offset + spaces, s, (size_t)s_len);
  581.     offset += s_len;
  582.  
  583.     if (spaces && !bdp->is_short)
  584.     {
  585.         /* insert post-padding */
  586.         copy_spaces(newp + offset + spaces, (size_t)(p_ts - spaces));
  587.         /* We're splitting a TAB, don't copy it. */
  588.         oldp++;
  589.         /* We allowed for that TAB, remember this now */
  590.         count++;
  591.     }
  592.  
  593.     if (spaces > 0)
  594.         offset += count;
  595.     mch_memmove(newp + offset, oldp, (size_t)(STRLEN(oldp) + 1));
  596.  
  597.     ml_replace(lnum, newp, FALSE);
  598.  
  599.     if (lnum == oap->end.lnum)
  600.     {
  601.         /* Set "']" mark to the end of the block instead of the end of
  602.          * the insert in the first line.  */
  603.         curbuf->b_op_end.lnum = oap->end.lnum;
  604.         curbuf->b_op_end.col = offset;
  605.     }
  606.     } /* for all lnum */
  607.  
  608.     changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
  609.  
  610.     State = oldstate;
  611. }
  612. #endif
  613.  
  614. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  615. /*
  616.  * op_reindent - handle reindenting a block of lines.
  617.  */
  618.     void
  619. op_reindent(oap, how)
  620.     oparg_T    *oap;
  621.     int        (*how) __ARGS((void));
  622. {
  623.     long    i;
  624.     char_u    *l;
  625.     int        count;
  626.     linenr_T    first_changed = 0;
  627.     linenr_T    last_changed = 0;
  628.     linenr_T    start_lnum = curwin->w_cursor.lnum;
  629.  
  630.     for (i = oap->line_count; --i >= 0 && !got_int; )
  631.     {
  632.     /* it's a slow thing to do, so give feedback so there's no worry that
  633.      * the computer's just hung. */
  634.  
  635.     if (i > 1
  636.         && (i % 50 == 0 || i == oap->line_count - 1)
  637.         && oap->line_count > p_report)
  638.         smsg((char_u *)_("%ld lines to indent... "), i);
  639.  
  640.     /*
  641.      * Be vi-compatible: For lisp indenting the first line is not
  642.      * indented, unless there is only one line.
  643.      */
  644. #ifdef FEAT_LISP
  645.     if (i != oap->line_count - 1 || oap->line_count == 1
  646.                             || how != get_lisp_indent)
  647. #endif
  648.     {
  649.         l = skipwhite(ml_get_curline());
  650.         if (*l == NUL)            /* empty or blank line */
  651.         count = 0;
  652.         else
  653.         count = how();            /* get the indent for this line */
  654.  
  655.         if (set_indent(count, SIN_UNDO))
  656.         {
  657.         /* did change the indent, call changed_lines() later */
  658.         if (first_changed == 0)
  659.             first_changed = curwin->w_cursor.lnum;
  660.         last_changed = curwin->w_cursor.lnum;
  661.         }
  662.     }
  663.     ++curwin->w_cursor.lnum;
  664.     }
  665.  
  666.     /* put cursor on first non-blank of indented line */
  667.     curwin->w_cursor.lnum = start_lnum;
  668.     beginline(BL_SOL | BL_FIX);
  669.  
  670.     /* Mark changed lines so that they will be redrawn.  When Visual
  671.      * highlighting was present, need to continue until the last line.  When
  672.      * there is no change still need to remove the Visual highlighting. */
  673.     if (last_changed != 0)
  674.     changed_lines(first_changed, 0,
  675. #ifdef FEAT_VISUAL
  676.         oap->is_VIsual ? start_lnum + oap->line_count :
  677. #endif
  678.         last_changed + 1, 0L);
  679. #ifdef FEAT_VISUAL
  680.     else if (oap->is_VIsual)
  681.     redraw_curbuf_later(INVERTED);
  682. #endif
  683.  
  684.     if (oap->line_count > p_report)
  685.     {
  686.     i = oap->line_count - (i + 1);
  687.     if (i == 1)
  688.         MSG(_("1 line indented "));
  689.     else
  690.         smsg((char_u *)_("%ld lines indented "), i);
  691.     }
  692.     /* set '[ and '] marks */
  693.     curbuf->b_op_start = oap->start;
  694.     curbuf->b_op_end = oap->end;
  695. }
  696. #endif /* defined(FEAT_LISP) || defined(FEAT_CINDENT) */
  697.  
  698. #ifdef FEAT_EVAL
  699. /*
  700.  * Keep the last expression line here, for repeating.
  701.  */
  702. static char_u    *expr_line = NULL;
  703.  
  704. /*
  705.  * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
  706.  * Returns '=' when OK, NUL otherwise.
  707.  */
  708.     int
  709. get_expr_register()
  710. {
  711.     char_u    *new_line;
  712.  
  713.     new_line = getcmdline('=', 0L, 0);
  714.     if (new_line == NULL)
  715.     return NUL;
  716.     if (*new_line == NUL)    /* use previous line */
  717.     vim_free(new_line);
  718.     else
  719.     set_expr_line(new_line);
  720.     return '=';
  721. }
  722.  
  723. /*
  724.  * Set the expression for the '=' register.
  725.  * Argument must be an allocated string.
  726.  */
  727.     void
  728. set_expr_line(new_line)
  729.     char_u    *new_line;
  730. {
  731.     vim_free(expr_line);
  732.     expr_line = new_line;
  733. }
  734.  
  735. /*
  736.  * Get the result of the '=' register expression.
  737.  * Returns a pointer to allocated memory, or NULL for failure.
  738.  */
  739.     static char_u *
  740. get_expr_line()
  741. {
  742.     char_u    *expr_copy;
  743.     char_u    *rv;
  744.  
  745.     if (expr_line == NULL)
  746.     return NULL;
  747.  
  748.     /* Make a copy of the expression, because evaluating it may cause it to be
  749.      * changed. */
  750.     expr_copy = vim_strsave(expr_line);
  751.     if (expr_copy == NULL)
  752.     return NULL;
  753.  
  754.     rv = eval_to_string(expr_copy, NULL);
  755.     vim_free(expr_copy);
  756.     return rv;
  757. }
  758. #endif /* FEAT_EVAL */
  759.  
  760. /*
  761.  * Check if 'regname' is a valid name of a yank register.
  762.  * Note: There is no check for 0 (default register), caller should do this
  763.  */
  764.     int
  765. valid_yank_reg(regname, writing)
  766.     int        regname;
  767.     int        writing;        /* if TRUE check for writable registers */
  768. {
  769.     if (       (regname > 0 && ASCII_ISALNUM(regname))
  770.         || (!writing && vim_strchr((char_u *)
  771. #ifdef FEAT_EVAL
  772.                     "/.%#:="
  773. #else
  774.                     "/.%#:"
  775. #endif
  776.                     , regname) != NULL)
  777.         || regname == '"'
  778.         || regname == '-'
  779.         || regname == '_'
  780. #ifdef FEAT_CLIPBOARD
  781.         || regname == '*'
  782.         || regname == '+'
  783. #endif
  784.                             )
  785.     return TRUE;
  786.     return FALSE;
  787. }
  788.  
  789. /*
  790.  * Set y_current and y_append, according to the value of "regname".
  791.  * Cannot handle the '_' register.
  792.  *
  793.  * If regname is 0 and writing, use register 0
  794.  * If regname is 0 and reading, use previous register
  795.  */
  796.     static void
  797. get_yank_register(regname, writing)
  798.     int        regname;
  799.     int        writing;
  800. {
  801.     int        i;
  802.  
  803.     y_append = FALSE;
  804.     if ((regname == 0 || regname == '"') && !writing && y_previous != NULL)
  805.     {
  806.     y_current = y_previous;
  807.     return;
  808.     }
  809.     i = regname;
  810.     if (isdigit(i))
  811.     i -= '0';
  812.     else if (ASCII_ISLOWER(i))
  813.     i = CharOrdLow(i) + 10;
  814.     else if (ASCII_ISUPPER(i))
  815.     {
  816.     i = CharOrdUp(i) + 10;
  817.     y_append = TRUE;
  818.     }
  819.     else if (regname == '-')
  820.     i = DELETION_REGISTER;
  821. #ifdef FEAT_CLIPBOARD
  822.     /* When selection is not available, use register 0 instead of '*' */
  823.     else if (clip_star.available && regname == '*')
  824.     i = STAR_REGISTER;
  825.     /* When clipboard is not available, use register 0 instead of '+' */
  826.     else if (clip_plus.available && regname == '+')
  827.     i = PLUS_REGISTER;
  828. #endif
  829.     else        /* not 0-9, a-z, A-Z or '-': use register 0 */
  830.     i = 0;
  831.     y_current = &(y_regs[i]);
  832.     if (writing)    /* remember the register we write into for do_put() */
  833.     y_previous = y_current;
  834. }
  835.  
  836. #if defined(FEAT_MOUSE) || defined(PROTO)
  837. /*
  838.  * return TRUE if the current yank register has type MLINE
  839.  */
  840.     int
  841. yank_register_mline(regname)
  842.     int        regname;
  843. {
  844.     if (regname != 0 && !valid_yank_reg(regname, FALSE))
  845.     return FALSE;
  846.     if (regname == '_')        /* black hole is always empty */
  847.     return FALSE;
  848.     get_yank_register(regname, FALSE);
  849.     return (y_current->y_type == MLINE);
  850. }
  851. #endif
  852.  
  853. /*
  854.  * start or stop recording into a yank register
  855.  *
  856.  * return FAIL for failure, OK otherwise
  857.  */
  858.     int
  859. do_record(c)
  860.     int c;
  861. {
  862.     char_u    *p;
  863.     static int    regname;
  864.     struct yankreg *old_y_previous, *old_y_current;
  865.     int        retval;
  866.  
  867.     if (Recording == FALSE)        /* start recording */
  868.     {
  869.             /* registers 0-9, a-z and " are allowed */
  870.     if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
  871.         retval = FAIL;
  872.     else
  873.     {
  874.         Recording = TRUE;
  875.         showmode();
  876.         regname = c;
  877.         retval = OK;
  878.     }
  879.     }
  880.     else                /* stop recording */
  881.     {
  882.     /*
  883.      * Get the recorded key hits.  K_SPECIAL and CSI will be escaped, so
  884.      * that the register can be put into the typeahead buffer without
  885.      * translation.
  886.      */
  887.     Recording = FALSE;
  888.     MSG("");
  889.     p = get_recorded();
  890.     if (p == NULL)
  891.         retval = FAIL;
  892.     else
  893.     {
  894.         /*
  895.          * We don't want to change the default register here, so save and
  896.          * restore the current register name.
  897.          */
  898.         old_y_previous = y_previous;
  899.         old_y_current = y_current;
  900.  
  901.         retval = stuff_yank(regname, p);
  902.  
  903.         y_previous = old_y_previous;
  904.         y_current = old_y_current;
  905.     }
  906.     }
  907.     return retval;
  908. }
  909.  
  910. /*
  911.  * Stuff string "p" into yank register "regname" as a single line (append if
  912.  * uppercase).    "p" must have been alloced.
  913.  *
  914.  * return FAIL for failure, OK otherwise
  915.  */
  916.     static int
  917. stuff_yank(regname, p)
  918.     int        regname;
  919.     char_u    *p;
  920. {
  921.     char_u    *lp;
  922.     char_u    **pp;
  923.  
  924.     /* check for read-only register */
  925.     if (regname != 0 && !valid_yank_reg(regname, TRUE))
  926.     {
  927.     vim_free(p);
  928.     return FAIL;
  929.     }
  930.     if (regname == '_')            /* black hole: don't do anything */
  931.     {
  932.     vim_free(p);
  933.     return OK;
  934.     }
  935.     get_yank_register(regname, TRUE);
  936.     if (y_append && y_current->y_array != NULL)
  937.     {
  938.     pp = &(y_current->y_array[y_current->y_size - 1]);
  939.     lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
  940.     if (lp == NULL)
  941.     {
  942.         vim_free(p);
  943.         return FAIL;
  944.     }
  945.     STRCPY(lp, *pp);
  946.     STRCAT(lp, p);
  947.     vim_free(p);
  948.     vim_free(*pp);
  949.     *pp = lp;
  950.     }
  951.     else
  952.     {
  953.     free_yank_all();
  954.     if ((y_current->y_array =
  955.             (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
  956.     {
  957.         vim_free(p);
  958.         return FAIL;
  959.     }
  960.     y_current->y_array[0] = p;
  961.     y_current->y_size = 1;
  962.     y_current->y_type = MCHAR;  /* used to be MLINE, why? */
  963.     }
  964.     return OK;
  965. }
  966.  
  967. /*
  968.  * execute a yank register: copy it into the stuff buffer
  969.  *
  970.  * return FAIL for failure, OK otherwise
  971.  */
  972.     int
  973. do_execreg(regname, colon, addcr)
  974.     int        regname;
  975.     int        colon;        /* insert ':' before each line */
  976.     int        addcr;        /* always add '\n' to end of line */
  977. {
  978.     static int    lastc = NUL;
  979.     long    i;
  980.     char_u    *p;
  981.     int        retval = OK;
  982.     int        remap;
  983.  
  984.     if (regname == '@')            /* repeat previous one */
  985.     regname = lastc;
  986.                     /* check for valid regname */
  987.     if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
  988.     return FAIL;
  989.     lastc = regname;
  990.  
  991.     if (regname == '_')            /* black hole: don't stuff anything */
  992.     return OK;
  993.  
  994. #ifdef FEAT_CMDHIST
  995.     if (regname == ':')            /* use last command line */
  996.     {
  997.     if (last_cmdline == NULL)
  998.     {
  999.         EMSG(_(e_nolastcmd));
  1000.         return FAIL;
  1001.     }
  1002.     vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
  1003.     new_last_cmdline = NULL;
  1004.     retval = put_in_typebuf(last_cmdline, TRUE);
  1005.     }
  1006. #endif
  1007. #ifdef FEAT_EVAL
  1008.     else if (regname == '=')
  1009.     {
  1010.     p = get_expr_line();
  1011.     if (p == NULL)
  1012.         return FAIL;
  1013.     retval = put_in_typebuf(p, colon);
  1014.     vim_free(p);
  1015.     }
  1016. #endif
  1017.     else if (regname == '.')        /* use last inserted text */
  1018.     {
  1019.     p = get_last_insert_save();
  1020.     if (p == NULL)
  1021.     {
  1022.         EMSG(_(e_noinstext));
  1023.         return FAIL;
  1024.     }
  1025.     retval = put_in_typebuf(p, colon);
  1026.     vim_free(p);
  1027.     }
  1028.     else
  1029.     {
  1030.     get_yank_register(regname, FALSE);
  1031.     if (y_current->y_array == NULL)
  1032.         return FAIL;
  1033.  
  1034.     /* Disallow remaping for ":@r". */
  1035.     remap = colon ? REMAP_NONE : REMAP_YES;
  1036.  
  1037.     /*
  1038.      * Insert lines into typeahead buffer, from last one to first one.
  1039.      */
  1040.     for (i = y_current->y_size; --i >= 0; )
  1041.     {
  1042.         /* insert NL between lines and after last line if type is MLINE */
  1043.         if (y_current->y_type == MLINE || i < y_current->y_size - 1
  1044.                                      || addcr)
  1045.         {
  1046.         if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, FALSE) == FAIL)
  1047.             return FAIL;
  1048.         }
  1049.         if (ins_typebuf(y_current->y_array[i], remap, 0, TRUE, FALSE)
  1050.                                       == FAIL)
  1051.         return FAIL;
  1052.         if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, FALSE)
  1053.                                       == FAIL)
  1054.         return FAIL;
  1055.     }
  1056.     Exec_reg = TRUE;    /* disable the 'q' command */
  1057.     }
  1058.     return retval;
  1059. }
  1060.  
  1061.     static int
  1062. put_in_typebuf(s, colon)
  1063.     char_u    *s;
  1064.     int        colon;        /* add ':' before the line */
  1065. {
  1066.     int        retval = OK;
  1067.  
  1068.     if (colon)
  1069.     retval = ins_typebuf((char_u *)"\n", REMAP_YES, 0, TRUE, FALSE);
  1070.     if (retval == OK)
  1071.     retval = ins_typebuf(s, REMAP_YES, 0, TRUE, FALSE);
  1072.     if (colon && retval == OK)
  1073.     retval = ins_typebuf((char_u *)":", REMAP_YES, 0, TRUE, FALSE);
  1074.     return retval;
  1075. }
  1076.  
  1077. /*
  1078.  * Insert a yank register: copy it into the Read buffer.
  1079.  * Used by CTRL-R command and middle mouse button in insert mode.
  1080.  *
  1081.  * return FAIL for failure, OK otherwise
  1082.  */
  1083.     int
  1084. insert_reg(regname, literally)
  1085.     int        regname;
  1086.     int        literally;    /* insert literally, not as if typed */
  1087. {
  1088.     long    i;
  1089.     int        retval = OK;
  1090.     char_u    *arg;
  1091.     int        allocated;
  1092.  
  1093.     /*
  1094.      * It is possible to get into an endless loop by having CTRL-R a in
  1095.      * register a and then, in insert mode, doing CTRL-R a.
  1096.      * If you hit CTRL-C, the loop will be broken here.
  1097.      */
  1098.     ui_breakcheck();
  1099.     if (got_int)
  1100.     return FAIL;
  1101.  
  1102.     /* check for valid regname */
  1103.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  1104.     return FAIL;
  1105.  
  1106. #ifdef FEAT_CLIPBOARD
  1107.     if (regname == '*')
  1108.     {
  1109.     if (!clip_star.available)
  1110.         regname = 0;
  1111.     else
  1112.         clip_get_selection(&clip_star);
  1113.     }
  1114.     else if (regname == '+')
  1115.     {
  1116.     if (!clip_plus.available)
  1117.         regname = 0;
  1118.     else
  1119.         clip_get_selection(&clip_plus);
  1120.     }
  1121. #endif
  1122.  
  1123.     if (regname == '.')            /* insert last inserted text */
  1124.     retval = stuff_inserted(NUL, 1L, TRUE);
  1125.     else if (get_spec_reg(regname, &arg, &allocated, TRUE))
  1126.     {
  1127.     if (arg == NULL)
  1128.         return FAIL;
  1129.     stuffescaped(arg, literally);
  1130.     if (allocated)
  1131.         vim_free(arg);
  1132.     }
  1133.     else                /* name or number register */
  1134.     {
  1135.     get_yank_register(regname, FALSE);
  1136.     if (y_current->y_array == NULL)
  1137.         retval = FAIL;
  1138.     else
  1139.     {
  1140.         for (i = 0; i < y_current->y_size; ++i)
  1141.         {
  1142.         stuffescaped(y_current->y_array[i], literally);
  1143.         /*
  1144.          * Insert a newline between lines and after last line if
  1145.          * y_type is MLINE.
  1146.          */
  1147.         if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  1148.             stuffcharReadbuff('\n');
  1149.         }
  1150.     }
  1151.     }
  1152.  
  1153.     return retval;
  1154. }
  1155.  
  1156. /*
  1157.  * Stuff a string into the typeahead buffer, such that edit() will insert it
  1158.  * literally ("literally" TRUE) or interpret is as typed characters.
  1159.  */
  1160.     static void
  1161. stuffescaped(arg, literally)
  1162.     char_u    *arg;
  1163.     int        literally;
  1164. {
  1165.     int        c;
  1166.     char_u    *start;
  1167.  
  1168.     while (*arg != NUL)
  1169.     {
  1170.     /* Stuff a sequence of normal ASCII characters, that's fast.  Also
  1171.      * stuff K_SPECIAL to get the effect of a special key when "literally"
  1172.      * is TRUE. */
  1173.     start = arg;
  1174.     while ((*arg >= ' '
  1175. #ifndef EBCDIC
  1176.             && *arg < DEL /* EBCDIC: chars above space are normal */
  1177. #endif
  1178.             )
  1179.         || (*arg == K_SPECIAL && !literally))
  1180.         ++arg;
  1181.     if (arg > start)
  1182.         stuffReadbuffLen(start, (long)(arg - start));
  1183.  
  1184.     /* stuff a single special character */
  1185.     if (*arg != NUL)
  1186.     {
  1187. #ifdef FEAT_MBYTE
  1188.         if (has_mbyte)
  1189.         c = mb_ptr2char_adv(&arg);
  1190.         else
  1191. #endif
  1192.         c = *arg++;
  1193.         if (literally && ((c < ' ' && c != TAB) || c == DEL))
  1194.         stuffcharReadbuff(Ctrl_V);
  1195.         stuffcharReadbuff(c);
  1196.     }
  1197.     }
  1198. }
  1199.  
  1200. /*
  1201.  * If "regname" is a special register, return a pointer to its value.
  1202.  */
  1203.     static int
  1204. get_spec_reg(regname, argp, allocated, errmsg)
  1205.     int        regname;
  1206.     char_u    **argp;
  1207.     int        *allocated;
  1208.     int        errmsg;        /* give error message when failing */
  1209. {
  1210.     int        cnt;
  1211.  
  1212.     *argp = NULL;
  1213.     *allocated = FALSE;
  1214.     switch (regname)
  1215.     {
  1216.     case '%':        /* file name */
  1217.         if (errmsg)
  1218.         check_fname();    /* will give emsg if not set */
  1219.         *argp = curbuf->b_fname;
  1220.         return TRUE;
  1221.  
  1222.     case '#':        /* alternate file name */
  1223.         *argp = getaltfname(errmsg);    /* may give emsg if not set */
  1224.         return TRUE;
  1225.  
  1226. #ifdef FEAT_EVAL
  1227.     case '=':        /* result of expression */
  1228.         *argp = get_expr_line();
  1229.         *allocated = TRUE;
  1230.         return TRUE;
  1231. #endif
  1232.  
  1233.     case ':':        /* last command line */
  1234.         if (last_cmdline == NULL && errmsg)
  1235.         EMSG(_(e_nolastcmd));
  1236.         *argp = last_cmdline;
  1237.         return TRUE;
  1238.  
  1239.     case '/':        /* last search-pattern */
  1240.         if (last_search_pat() == NULL && errmsg)
  1241.         EMSG(_(e_noprevre));
  1242.         *argp = last_search_pat();
  1243.         return TRUE;
  1244.  
  1245.     case '.':        /* last inserted text */
  1246.         *argp = get_last_insert_save();
  1247.         *allocated = TRUE;
  1248.         if (*argp == NULL && errmsg)
  1249.         EMSG(_(e_noinstext));
  1250.         return TRUE;
  1251.  
  1252. #ifdef FEAT_SEARCHPATH
  1253.     case Ctrl_F:        /* Filename under cursor */
  1254.     case Ctrl_P:        /* Path under cursor, expand via "path" */
  1255.         if (!errmsg)
  1256.         return FALSE;
  1257.         *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
  1258.                 | (regname == Ctrl_P ? FNAME_EXP : 0), 1L);
  1259.         *allocated = TRUE;
  1260.         return TRUE;
  1261. #endif
  1262.  
  1263.     case Ctrl_W:        /* word under cursor */
  1264.     case Ctrl_A:        /* WORD (mnemonic All) under cursor */
  1265.         if (!errmsg)
  1266.         return FALSE;
  1267.         cnt = find_ident_under_cursor(argp, regname == Ctrl_W
  1268.                    ?  (FIND_IDENT|FIND_STRING) : FIND_STRING);
  1269.         *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
  1270.         *allocated = TRUE;
  1271.         return TRUE;
  1272.  
  1273.     case '_':        /* black hole: always empty */
  1274.         *argp = (char_u *)"";
  1275.         return TRUE;
  1276.     }
  1277.  
  1278.     return FALSE;
  1279. }
  1280.  
  1281. /*
  1282.  * paste a yank register into the command line.
  1283.  * used by CTRL-R command in command-line mode
  1284.  * insert_reg() can't be used here, because special characters from the
  1285.  * register contents will be interpreted as commands.
  1286.  *
  1287.  * return FAIL for failure, OK otherwise
  1288.  */
  1289.     int
  1290. cmdline_paste(regname, literally)
  1291.     int regname;
  1292.     int literally;    /* Insert text literally instead of "as typed" */
  1293. {
  1294.     long    i;
  1295.     char_u    *arg;
  1296.     int        allocated;
  1297.  
  1298.     /* check for valid regname; also accept special characters for CTRL-R in
  1299.      * the command line */
  1300.     if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W
  1301.         && regname != Ctrl_A && !valid_yank_reg(regname, FALSE))
  1302.     return FAIL;
  1303.  
  1304.     /* A register containing CTRL-R can cause an endless loop.  Allow using
  1305.      * CTRL-C to break the loop. */
  1306.     line_breakcheck();
  1307.     if (got_int)
  1308.     return FAIL;
  1309.  
  1310. #ifdef FEAT_CLIPBOARD
  1311.     if (regname == '*')
  1312.     {
  1313.     if (!clip_star.available)
  1314.         regname = 0;
  1315.     else
  1316.         clip_get_selection(&clip_star);
  1317.     }
  1318.     else if (regname == '+')
  1319.     {
  1320.     if (!clip_plus.available)
  1321.         regname = 0;
  1322.     else
  1323.         clip_get_selection(&clip_plus);
  1324.     }
  1325. #endif
  1326.  
  1327.     if (get_spec_reg(regname, &arg, &allocated, TRUE))
  1328.     {
  1329.     if (arg == NULL)
  1330.         return FAIL;
  1331.     cmdline_paste_str(arg, literally);
  1332.     if (allocated)
  1333.         vim_free(arg);
  1334.     return OK;
  1335.     }
  1336.  
  1337.     get_yank_register(regname, FALSE);
  1338.     if (y_current->y_array == NULL)
  1339.     return FAIL;
  1340.  
  1341.     for (i = 0; i < y_current->y_size; ++i)
  1342.     {
  1343.     cmdline_paste_str(y_current->y_array[i], literally);
  1344.  
  1345.     /* insert ^M between lines and after last line if type is MLINE */
  1346.     if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  1347.         cmdline_paste_str((char_u *)"\r", literally);
  1348.     }
  1349.     return OK;
  1350. }
  1351.  
  1352. /*
  1353.  * Put a string on the command line.
  1354.  * When "literally" is TRUE, insert literally.
  1355.  * When "literally" is FALSE, insert as typed, but don't leave the command
  1356.  * line.
  1357.  */
  1358.     static void
  1359. cmdline_paste_str(s, literally)
  1360.     char_u    *s;
  1361.     int        literally;
  1362. {
  1363.     int        c, cv;
  1364.  
  1365.     if (literally)
  1366.     put_on_cmdline(s, -1, TRUE);
  1367.     else
  1368.     while (*s != NUL)
  1369.     {
  1370.         cv = *s;
  1371.         if (cv == Ctrl_V && s[1])
  1372.         ++s;
  1373. #ifdef FEAT_MBYTE
  1374.         if (has_mbyte)
  1375.         c = mb_ptr2char_adv(&s);
  1376.         else
  1377. #endif
  1378.         c = *s++;
  1379.         if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CR || c == NL
  1380. #ifdef UNIX
  1381.             || c == intr_char
  1382. #endif
  1383.             || (c == Ctrl_BSL && *s == Ctrl_N))
  1384.         stuffcharReadbuff(Ctrl_V);
  1385.         stuffcharReadbuff(c);
  1386.     }
  1387. }
  1388.  
  1389. /*
  1390.  * op_delete - handle a delete operation
  1391.  *
  1392.  * return FAIL if undo failed, OK otherwise.
  1393.  */
  1394.     int
  1395. op_delete(oap)
  1396.     oparg_T   *oap;
  1397. {
  1398.     int            n;
  1399.     linenr_T        lnum;
  1400.     char_u        *ptr;
  1401.     char_u        *newp, *oldp;
  1402.     linenr_T        old_lcount = curbuf->b_ml.ml_line_count;
  1403.     int            did_yank = FALSE;
  1404.     struct block_def    bd;
  1405.  
  1406.     if (curbuf->b_ml.ml_flags & ML_EMPTY)        /* nothing to do */
  1407.     return OK;
  1408.  
  1409.     /* Nothing to delete, return here.    Do prepare undo, for op_change(). */
  1410.     if (oap->empty)
  1411.     return u_save_cursor();
  1412.  
  1413.     if (!curbuf->b_p_ma)
  1414.     {
  1415.     EMSG(_(e_modifiable));
  1416.     return FAIL;
  1417.     }
  1418.  
  1419. #ifdef FEAT_CLIPBOARD
  1420.     /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */
  1421.     if (oap->regname == 0 && clip_unnamed)
  1422.     oap->regname = '*';
  1423.     if (!clip_star.available && oap->regname == '*')
  1424.     oap->regname = 0;
  1425.     if (!clip_plus.available && oap->regname == '+')
  1426.     oap->regname = 0;
  1427. #endif
  1428.  
  1429. #ifdef FEAT_MBYTE
  1430.     if (has_mbyte)
  1431.     mb_adjust_opend(oap);
  1432. #endif
  1433.  
  1434. /*
  1435.  * Imitate the strange Vi behaviour: If the delete spans more than one line
  1436.  * and motion_type == MCHAR and the result is a blank line, make the delete
  1437.  * linewise.  Don't do this for the change command or Visual mode.
  1438.  */
  1439.     if (       oap->motion_type == MCHAR
  1440. #ifdef FEAT_VISUAL
  1441.         && !oap->is_VIsual
  1442. #endif
  1443.         && oap->line_count > 1
  1444.         && oap->op_type == OP_DELETE)
  1445.     {
  1446.     ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive;
  1447.     ptr = skipwhite(ptr);
  1448.     if (*ptr == NUL && inindent(0))
  1449.         oap->motion_type = MLINE;
  1450.     }
  1451.  
  1452. /*
  1453.  * Check for trying to delete (e.g. "D") in an empty line.
  1454.  * Note: For the change operator it is ok.
  1455.  */
  1456.     if (       oap->motion_type == MCHAR
  1457.         && oap->line_count == 1
  1458.         && oap->op_type == OP_DELETE
  1459.         && *ml_get(oap->start.lnum) == NUL)
  1460.     {
  1461.     /*
  1462.      * It's an error to operate on an empty region, when 'E' inclucded in
  1463.      * 'cpoptions' (Vi compatible).
  1464.      */
  1465.     if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL)
  1466.         beep_flush();
  1467.     return OK;
  1468.     }
  1469.  
  1470. /*
  1471.  * Do a yank of whatever we're about to delete.
  1472.  * If a yank register was specified, put the deleted text into that register.
  1473.  * For the black hole register '_' don't yank anything.
  1474.  */
  1475.     if (oap->regname != '_')
  1476.     {
  1477.     if (oap->regname != 0)
  1478.     {
  1479.         /* check for read-only register */
  1480.         if (!valid_yank_reg(oap->regname, TRUE))
  1481.         {
  1482.         beep_flush();
  1483.         return OK;
  1484.         }
  1485.         get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */
  1486.         if (op_yank(oap, TRUE, FALSE) == OK)   /* yank without message */
  1487.         did_yank = TRUE;
  1488.     }
  1489.  
  1490.     /*
  1491.      * Put deleted text into register 1 and shift number registers if the
  1492.      * delete contains a line break, or when a regname has been specified.
  1493.      */
  1494.     if (oap->regname != 0 || oap->motion_type == MLINE
  1495.                    || oap->line_count > 1 || oap->use_reg_one)
  1496.     {
  1497.         y_current = &y_regs[9];
  1498.         free_yank_all();            /* free register nine */
  1499.         for (n = 9; n > 1; --n)
  1500.         y_regs[n] = y_regs[n - 1];
  1501.         y_previous = y_current = &y_regs[1];
  1502.         y_regs[1].y_array = NULL;        /* set register one to empty */
  1503.         if (op_yank(oap, TRUE, FALSE) == OK)
  1504.         did_yank = TRUE;
  1505.     }
  1506.  
  1507.     /* Yank into small delete register when no register specified and the
  1508.      * delete is within one line. */
  1509.     if (oap->regname == 0 && oap->motion_type != MLINE
  1510.                               && oap->line_count == 1)
  1511.     {
  1512.         oap->regname = '-';
  1513.         get_yank_register(oap->regname, TRUE);
  1514.         if (op_yank(oap, TRUE, FALSE) == OK)
  1515.         did_yank = TRUE;
  1516.         oap->regname = 0;
  1517.     }
  1518.  
  1519.     /*
  1520.      * If there's too much stuff to fit in the yank register, then get a
  1521.      * confirmation before doing the delete. This is crude, but simple.
  1522.      * And it avoids doing a delete of something we can't put back if we
  1523.      * want.
  1524.      */
  1525.     if (!did_yank)
  1526.     {
  1527.         msg_silent = 0;    /* must display the prompt */
  1528.         if (ask_yesno((char_u *)_("cannot yank; delete anyway"), TRUE)
  1529.                                        != 'y')
  1530.         {
  1531.         EMSG(_(e_abort));
  1532.         return FAIL;
  1533.         }
  1534.     }
  1535.     }
  1536.  
  1537. /*
  1538.  * block mode delete
  1539.  */
  1540.     if (oap->block_mode)
  1541.     {
  1542.     if (u_save((linenr_T)(oap->start.lnum - 1),
  1543.                    (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1544.         return FAIL;
  1545.  
  1546.     for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum)
  1547.     {
  1548.         block_prep(oap, &bd, lnum, TRUE);
  1549.         if (bd.textlen == 0)    /* nothing to delete */
  1550.         continue;
  1551.  
  1552.         /* Adjust cursor position for tab replaced by spaces and 'lbr'. */
  1553.         if (lnum == curwin->w_cursor.lnum)
  1554.         curwin->w_cursor.col = bd.textcol + bd.startspaces;
  1555.  
  1556.         /* n == number of chars deleted
  1557.          * If we delete a TAB, it may be replaced by several characters.
  1558.          * Thus the number of characters may increase!
  1559.          */
  1560.         n = bd.textlen - bd.startspaces - bd.endspaces;
  1561.         oldp = ml_get(lnum);
  1562.         newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
  1563.         if (newp == NULL)
  1564.         continue;
  1565.         /* copy up to deleted part */
  1566.         mch_memmove(newp, oldp, (size_t)bd.textcol);
  1567.         /* insert spaces */
  1568.         copy_spaces(newp + bd.textcol,
  1569.                      (size_t)(bd.startspaces + bd.endspaces));
  1570.         /* copy the part after the deleted part */
  1571.         oldp += bd.textcol + bd.textlen;
  1572.         mch_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
  1573.                               oldp, STRLEN(oldp) + 1);
  1574.         /* replace the line */
  1575.         ml_replace(lnum, newp, FALSE);
  1576.     }
  1577.  
  1578.     /* Put cursor back at start of changed block */
  1579.     changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
  1580.                                oap->end.lnum + 1, 0L);
  1581.     oap->line_count = 0;        /* no lines deleted */
  1582.     }
  1583.     else if (oap->motion_type == MLINE)
  1584.     {
  1585.     if (oap->op_type == OP_CHANGE)
  1586.     {
  1587.         /* Delete the lines except the first one.  Temporarily move the
  1588.          * cursor to the next line.  Save the current line number, if the
  1589.          * last line is deleted it may be changed.
  1590.          */
  1591.         if (oap->line_count > 1)
  1592.         {
  1593.         lnum = curwin->w_cursor.lnum;
  1594.         ++curwin->w_cursor.lnum;
  1595.         del_lines((long)(oap->line_count - 1), TRUE);
  1596.         curwin->w_cursor.lnum = lnum;
  1597.         }
  1598.         if (u_save_cursor() == FAIL)
  1599.         return FAIL;
  1600.         if (curbuf->b_p_ai)            /* don't delete indent */
  1601.         {
  1602.         beginline(BL_WHITE);        /* cursor on first non-white */
  1603.         did_ai = TRUE;            /* delete the indent when ESC hit */
  1604.         ai_col = curwin->w_cursor.col;
  1605.         }
  1606.         else
  1607.         beginline(0);            /* cursor in column 0 */
  1608.         truncate_line(FALSE);   /* delete the rest of the line */
  1609.                     /* leave cursor past last char in line */
  1610.         if (oap->line_count > 1)
  1611.         u_clearline();        /* "U" command not possible after "2cc" */
  1612.     }
  1613.     else
  1614.     {
  1615.         del_lines(oap->line_count, TRUE);
  1616.         beginline(BL_WHITE | BL_FIX);
  1617.         u_clearline();    /* "U" command not possible after "dd" */
  1618.     }
  1619.     }
  1620.     else if (oap->line_count == 1)    /* delete characters within one line */
  1621.     {
  1622.     if (u_save_cursor() == FAIL)
  1623.         return FAIL;
  1624.     /* if 'cpoptions' contains '$', display '$' at end of change */
  1625.     if (       vim_strchr(p_cpo, CPO_DOLLAR) != NULL
  1626.         && oap->op_type == OP_CHANGE
  1627.         && oap->end.lnum == curwin->w_cursor.lnum
  1628. #ifdef FEAT_VISUAL
  1629.         && !oap->is_VIsual
  1630. #endif
  1631.         )
  1632.         display_dollar(oap->end.col - !oap->inclusive);
  1633.  
  1634.     n = oap->end.col - oap->start.col + 1 - !oap->inclusive;
  1635. #ifdef FEAT_VIRTUALEDIT
  1636.  
  1637.     if (virtual_active())
  1638.     {
  1639.         /* fix up things for virtualedit-delete:
  1640.          * make sure the coladds are in the right order, and
  1641.          * break the tabs which are going to get in our way
  1642.          */
  1643.         char_u    *curline = ml_get_curline();
  1644.         int        oldcol = getviscol();
  1645.         int        len;
  1646.         int        endcol;
  1647.  
  1648.         if (oap->start.col == oap->end.col
  1649.             && oap->end.coladd < oap->start.coladd)
  1650.         {
  1651.         colnr_T tmp = oap->start.coladd;
  1652.         oap->start.coladd = oap->end.coladd;
  1653.         oap->end.coladd = tmp;
  1654.  
  1655.         curwin->w_cursor.coladd = oap->start.coladd;
  1656.         }
  1657.  
  1658.         if (curline[oap->start.col] == '\t')
  1659.         {
  1660.         endcol = getviscol2(oap->end.col, oap->end.coladd);
  1661.         coladvance_force(getviscol2(oap->start.col, oap->start.coladd));
  1662.         oap->start.col = curwin->w_cursor.col;
  1663.         oap->start.coladd = 0;
  1664.         coladvance(endcol);
  1665.         oap->end.col = curwin->w_cursor.col;
  1666.         oap->end.coladd = curwin->w_cursor.coladd;
  1667.         coladvance(oldcol);
  1668.         curline = ml_get_curline();
  1669.         }
  1670.  
  1671.         if (curline[oap->end.col] == '\t')
  1672.         {
  1673.         coladvance_force(getviscol2(oap->end.col, oap->end.coladd));
  1674.         oap->end.col = curwin->w_cursor.col;
  1675.         oap->end.coladd = 0;
  1676.         coladvance(oldcol);
  1677.         curline = ml_get_curline();
  1678.         }
  1679.  
  1680.         n = oap->end.col - oap->start.col + 1 - !oap->inclusive;
  1681.         len = (int)STRLEN(curline);
  1682.  
  1683.         if (oap->end.coladd != 0 && (int)oap->end.col >= len - 1
  1684.             && !(oap->start.coladd && (int)oap->end.col >= len - 1))
  1685.         n++;
  1686.         /* Delete at least one character (e.g, when on a control char). */
  1687.         if (n == 0 && oap->start.coladd != oap->end.coladd)
  1688.         n = 1;
  1689.  
  1690.         /* When deleted a char in the line, reset coladd. */
  1691.         if (gchar_cursor() != NUL)
  1692.         curwin->w_cursor.coladd = 0;
  1693.     }
  1694. #endif
  1695.     (void)del_bytes((long)n, restart_edit == NUL);
  1696.     }
  1697.     else                /* delete characters between lines */
  1698.     {
  1699.     if (u_save_cursor() == FAIL)    /* save first line for undo */
  1700.         return FAIL;
  1701.     truncate_line(TRUE);        /* delete from cursor to end of line */
  1702.  
  1703.     oap->start = curwin->w_cursor;    /* remember curwin->w_cursor */
  1704.     ++curwin->w_cursor.lnum;
  1705.                     /* includes save for undo */
  1706.     del_lines((long)(oap->line_count - 2), TRUE);
  1707.  
  1708.     if (u_save_cursor() == FAIL)    /* save last line for undo */
  1709.         return FAIL;
  1710.     u_clearline();            /* "U" should not be possible now */
  1711.     /* delete from start of line until op_end */
  1712.     curwin->w_cursor.col = 0;
  1713.     (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive),
  1714.                              restart_edit == NUL);
  1715.     curwin->w_cursor = oap->start;    /* restore curwin->w_cursor */
  1716.  
  1717.     (void)do_join(FALSE);
  1718.     }
  1719.  
  1720.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  1721.  
  1722.     /*
  1723.      * Set "'[" and "']" marks.
  1724.      */
  1725.     curbuf->b_op_start = oap->start;
  1726.     if (oap->block_mode)
  1727.     {
  1728.     curbuf->b_op_end.lnum = oap->end.lnum;
  1729.     curbuf->b_op_end.col = oap->start.col;
  1730.     }
  1731.     else
  1732.     curbuf->b_op_end = oap->start;
  1733.  
  1734.     return OK;
  1735. }
  1736.  
  1737. #ifdef FEAT_MBYTE
  1738. /*
  1739.  * Adjust end of operating area for ending on a multi-byte character.
  1740.  * Used for deletion.
  1741.  */
  1742.     static void
  1743. mb_adjust_opend(oap)
  1744.     oparg_T    *oap;
  1745. {
  1746.     char_u    *p;
  1747.  
  1748.     if (oap->inclusive)
  1749.     {
  1750.     p = ml_get(oap->end.lnum);
  1751.     oap->end.col += mb_tail_off(p, p + oap->end.col);
  1752.     }
  1753. }
  1754. #endif
  1755.  
  1756. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  1757. /*
  1758.  * Replace a whole area with one character.
  1759.  */
  1760.     int
  1761. op_replace(oap, c)
  1762.     oparg_T   *oap;
  1763.     int        c;
  1764. {
  1765.     int            n, numc;
  1766.     char_u        *newp, *oldp;
  1767.     size_t        oldlen;
  1768.     struct block_def    bd;
  1769.  
  1770.     if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty)
  1771.     return OK;        /* nothing to do */
  1772.  
  1773. #ifdef FEAT_MBYTE
  1774.     if (has_mbyte)
  1775.     mb_adjust_opend(oap);
  1776. #endif
  1777.  
  1778.     if (u_save((linenr_T)(oap->start.lnum - 1),
  1779.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1780.     return FAIL;
  1781.  
  1782.     /*
  1783.      * block mode replace
  1784.      */
  1785.     if (oap->block_mode)
  1786.     {
  1787.         bd.is_MAX = (curwin->w_curswant == MAXCOL);
  1788.     for ( ; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum)
  1789.     {
  1790.         block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
  1791.         if (bd.textlen == 0 && !virtual_active())    /* nothing to delete */
  1792.         continue;
  1793.  
  1794.         /* n == number of extra chars required
  1795.          * If we split a TAB, it may be replaced by several characters.
  1796.          * Thus the number of characters may increase!
  1797.          */
  1798. #ifdef FEAT_VIRTUALEDIT
  1799.         /* If the range starts in virtual space, count the initial
  1800.          * coladd offset as part of "startspaces" */
  1801.         if (virtual_active() && bd.is_short && *bd.textstart == NUL)
  1802.         {
  1803.         pos_T vpos;
  1804.  
  1805.         getvpos(&vpos, oap->start_vcol);
  1806.         bd.startspaces += vpos.coladd;
  1807.         n = bd.startspaces;
  1808.         }
  1809.         else
  1810. #endif
  1811.         /* allow for pre spaces */
  1812.         n = (bd.startspaces ? bd.start_char_vcols - 1 : 0);
  1813.  
  1814.         /* allow for post spp */
  1815.         n += (bd.endspaces
  1816. #ifdef FEAT_VIRTUALEDIT
  1817.             && !bd.is_oneChar
  1818. #endif
  1819.             && bd.end_char_vcols > 0 ? bd.end_char_vcols - 1 : 0);
  1820.         /* Figure out how many characters to replace. */
  1821.         numc = oap->end_vcol - oap->start_vcol + 1;
  1822.         if (bd.is_short && (!virtual_active() || bd.is_MAX))
  1823.         numc -= (oap->end_vcol - bd.end_vcol) + 1;
  1824.         /* oldlen includes textlen, so don't double count */
  1825.         n += numc - bd.textlen;
  1826.  
  1827.         oldp = ml_get_curline();
  1828.         oldlen = STRLEN(oldp);
  1829.         newp = alloc_check((unsigned)oldlen + 1 + n);
  1830.         if (newp == NULL)
  1831.         continue;
  1832.         vim_memset(newp, NUL, (size_t)(oldlen + 1 + n));
  1833.         /* copy up to deleted part */
  1834.         mch_memmove(newp, oldp, (size_t)bd.textcol);
  1835.         oldp += bd.textcol + bd.textlen;
  1836.         /* insert pre-spaces */
  1837.         copy_spaces(newp + bd.textcol, (size_t)bd.startspaces);
  1838.         /* insert replacement chars CHECK FOR ALLOCATED SPACE */
  1839.         copy_chars(newp + STRLEN(newp), (size_t)numc, c);
  1840.         if (!bd.is_short)
  1841.         {
  1842.         /* insert post-spaces */
  1843.         copy_spaces(newp + STRLEN(newp), (size_t)bd.endspaces);
  1844.         /* copy the part after the changed part */
  1845.         mch_memmove(newp + STRLEN(newp), oldp, STRLEN(oldp) + 1);
  1846.         }
  1847.         /* replace the line */
  1848.         ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  1849.     }
  1850.     }
  1851.     else
  1852.     {
  1853.     /*
  1854.      * MCHAR and MLINE motion replace.
  1855.      */
  1856.     if (oap->motion_type == MLINE)
  1857.     {
  1858.         oap->start.col = 0;
  1859.         curwin->w_cursor.col = 0;
  1860.         oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  1861.         if (oap->end.col)
  1862.         --oap->end.col;
  1863.     }
  1864.     else if (!oap->inclusive)
  1865.         dec(&(oap->end));
  1866.  
  1867.     while (ltoreq(curwin->w_cursor, oap->end))
  1868.     {
  1869.         n = gchar_cursor();
  1870.         if (n != NUL)
  1871.         {
  1872. #ifdef FEAT_MBYTE
  1873.         if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1)
  1874.         {
  1875.             /* This is slow, but it handles replacing a single-byte
  1876.              * with a multi-byte and the other way around. */
  1877.             n = State;
  1878.             State = REPLACE;
  1879.             ins_char(c);
  1880.             State = n;
  1881.         }
  1882.         else
  1883. #endif
  1884.         {
  1885. #ifdef FEAT_VIRTUALEDIT
  1886.             if (n == TAB)
  1887.             {
  1888.             int end_vcol = 0;
  1889.  
  1890.             if (curwin->w_cursor.lnum == oap->end.lnum)
  1891.             {
  1892.                 /* oap->end has to be recalculated when
  1893.                  * the tab breaks */
  1894.                 end_vcol = getviscol2(oap->end.col,
  1895.                                  oap->end.coladd);
  1896.             }
  1897.             coladvance_force(getviscol());
  1898.             if (curwin->w_cursor.lnum == oap->end.lnum)
  1899.                 getvpos(&oap->end, end_vcol);
  1900.             pchar(curwin->w_cursor, c);
  1901.             }
  1902. #endif
  1903.             pchar(curwin->w_cursor, c);
  1904.         }
  1905.         }
  1906. #ifdef FEAT_VIRTUALEDIT
  1907.         else if (virtual_active() && curwin->w_cursor.lnum == oap->end.lnum)
  1908.         {
  1909.         int virtcols = oap->end.coladd;
  1910.  
  1911.         if (curwin->w_cursor.lnum == oap->start.lnum
  1912.             && oap->start.col == oap->end.col && oap->start.coladd)
  1913.             virtcols -= oap->start.coladd;
  1914.  
  1915.         /* oap->end has been trimmed so it's effectively inclusive;
  1916.          * as a result an extra +1 must be counted so we don't
  1917.          * trample the NUL byte. */
  1918.         coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1);
  1919.         curwin->w_cursor.col -= (virtcols + 1);
  1920.         for (; virtcols >= 0; virtcols--)
  1921.         {
  1922.             pchar(curwin->w_cursor, c);
  1923.             if (inc(&curwin->w_cursor) == -1)
  1924.             break;
  1925.         }
  1926.         }
  1927. #endif
  1928.  
  1929.         /* Advance to next character, stop at the end of the file. */
  1930.         if (inc(&curwin->w_cursor) == -1)
  1931.         break;
  1932.     }
  1933.     }
  1934.  
  1935.     curwin->w_cursor = oap->start;
  1936.     check_cursor();
  1937.     changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L);
  1938.  
  1939.     /* Set "'[" and "']" marks. */
  1940.     curbuf->b_op_start = oap->start;
  1941.     curbuf->b_op_end = oap->end;
  1942.  
  1943.     return OK;
  1944. }
  1945. #endif
  1946.  
  1947. /*
  1948.  * Handle the (non-standard vi) tilde operator.  Also for "gu" and "gU".
  1949.  */
  1950.     void
  1951. op_tilde(oap)
  1952.     oparg_T    *oap;
  1953. {
  1954.     pos_T        pos;
  1955.     struct block_def    bd;
  1956.     int            did_change = 0;
  1957.  
  1958.     if (u_save((linenr_T)(oap->start.lnum - 1),
  1959.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1960.     return;
  1961.  
  1962.     pos = oap->start;
  1963.     if (oap->block_mode)            /* Visual block mode */
  1964.     {
  1965.     for (; pos.lnum <= oap->end.lnum; ++pos.lnum)
  1966.     {
  1967.         block_prep(oap, &bd, pos.lnum, FALSE);
  1968.         pos.col = bd.textcol;
  1969.         while (--bd.textlen >= 0)
  1970.         {
  1971.         did_change |= swapchar(oap->op_type, &pos);
  1972.         if (inc(&pos) == -1)        /* at end of file */
  1973.             break;
  1974.         }
  1975.     }
  1976.     if (did_change)
  1977.         changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
  1978.     }
  1979.     else                    /* not block mode */
  1980.     {
  1981.     if (oap->motion_type == MLINE)
  1982.     {
  1983.         oap->start.col = 0;
  1984.         pos.col = 0;
  1985.         oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  1986.         if (oap->end.col)
  1987.         --oap->end.col;
  1988.     }
  1989.     else if (!oap->inclusive)
  1990.         dec(&(oap->end));
  1991.  
  1992.     while (ltoreq(pos, oap->end))
  1993.     {
  1994.         did_change |= swapchar(oap->op_type, &pos);
  1995.         if (inc(&pos) == -1)    /* at end of file */
  1996.         break;
  1997.     }
  1998.     if (did_change)
  1999.         changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1,
  2000.                                       0L);
  2001.     }
  2002.  
  2003. #ifdef FEAT_VISUAL
  2004.     if (!did_change && oap->is_VIsual)
  2005.     /* No change: need to remove the Visual selection */
  2006.     redraw_curbuf_later(INVERTED);
  2007. #endif
  2008.  
  2009.     /*
  2010.      * Set '[ and '] marks.
  2011.      */
  2012.     curbuf->b_op_start = oap->start;
  2013.     curbuf->b_op_end = oap->end;
  2014.  
  2015.     if (oap->line_count > p_report)
  2016.     {
  2017.     if (oap->line_count == 1)
  2018.         MSG(_("1 line ~ed"));
  2019.     else
  2020.         smsg((char_u *)_("%ld lines ~ed"), oap->line_count);
  2021.     }
  2022. }
  2023.  
  2024. /*
  2025.  * If op_type == OP_UPPER: make uppercase,
  2026.  * if op_type == OP_LOWER: make lowercase,
  2027.  * else swap case of character at 'pos'
  2028.  * returns TRUE when something actually changed.
  2029.  */
  2030.     int
  2031. swapchar(op_type, pos)
  2032.     int        op_type;
  2033.     pos_T    *pos;
  2034. {
  2035.     int        c;
  2036.     int        nc;
  2037.  
  2038.     c = gchar_pos(pos);
  2039.  
  2040.     /* Only do rot13 encoding for ASCII characters. */
  2041.     if (c >= 0x80 && op_type == OP_ROT13)
  2042.     return FALSE;
  2043.  
  2044. #ifdef FEAT_MBYTE
  2045.     if (enc_dbcs != 0 && c >= 0x100)    /* No lower/uppercase letter */
  2046.     return FALSE;
  2047. #endif
  2048.     nc = c;
  2049.     if (MB_ISLOWER(c))
  2050.     {
  2051.     if (op_type == OP_ROT13)
  2052.         nc = ROT13(c, 'a');
  2053.     else if (op_type != OP_LOWER)
  2054.         nc = MB_TOUPPER(c);
  2055.     }
  2056.     else if (MB_ISUPPER(c))
  2057.     {
  2058.     if (op_type == OP_ROT13)
  2059.         nc = ROT13(c, 'A');
  2060.     else if (op_type != OP_UPPER)
  2061.         nc = MB_TOLOWER(c);
  2062.     }
  2063.     if (nc != c)
  2064.     {
  2065. #ifdef FEAT_MBYTE
  2066.     if (enc_utf8 && (c >= 0x80 || nc >= 0x80))
  2067.     {
  2068.         pos_T   sp = curwin->w_cursor;
  2069.  
  2070.         curwin->w_cursor = *pos;
  2071.         del_char(FALSE);
  2072.         ins_char(nc);
  2073.         curwin->w_cursor = sp;
  2074.     }
  2075.     else
  2076. #endif
  2077.         pchar(*pos, nc);
  2078.     return TRUE;
  2079.     }
  2080.     return FALSE;
  2081. }
  2082.  
  2083. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  2084. /*
  2085.  * op_insert - Insert and append operators for Visual mode.
  2086.  */
  2087.     void
  2088. op_insert(oap, count1)
  2089.     oparg_T    *oap;
  2090.     long    count1;
  2091. {
  2092.     long        ins_len, pre_textlen = 0;
  2093.     char_u        *firstline, *ins_text;
  2094.     struct block_def    bd;
  2095.     int            i;
  2096.  
  2097.     if (u_save((linenr_T)(oap->start.lnum - 1),
  2098.            (linenr_T)(oap->end.lnum + 1)) == FAIL)
  2099.     return;
  2100.  
  2101.     /* edit() changes this - record it for OP_APPEND */
  2102.     bd.is_MAX = (curwin->w_curswant == MAXCOL);
  2103.  
  2104.     /* vis block is still marked. Get rid of it now. */
  2105.     curwin->w_cursor.lnum = oap->start.lnum;
  2106.     update_screen(INVERTED);
  2107.  
  2108.     if (oap->block_mode)
  2109.     {
  2110. #ifdef FEAT_VIRTUALEDIT
  2111.     /* When 'virtualedit' is used, need to insert the extra spaces before
  2112.      * doing block_prep().  When only "block" is used, virtual edit is
  2113.      * already disabled, but still need it when calling
  2114.      * coladvance_force(). */
  2115.     if (curwin->w_cursor.coladd > 0)
  2116.     {
  2117.         int        old_ve_flags = ve_flags;
  2118.  
  2119.         ve_flags = VE_ALL;
  2120.         coladvance_force(oap->op_type == OP_APPEND
  2121.                        ? oap->end_vcol + 1 : getviscol());
  2122.         if (oap->op_type == OP_APPEND)
  2123.         --curwin->w_cursor.col;
  2124.         ve_flags = old_ve_flags;
  2125.     }
  2126. #endif
  2127.     /* Get the info about the block before entering the text */
  2128.     block_prep(oap, &bd, oap->start.lnum, TRUE);
  2129.     firstline = ml_get(oap->start.lnum) + bd.textcol;
  2130.     if (oap->op_type == OP_APPEND)
  2131.         firstline += bd.textlen;
  2132.     pre_textlen = (long)STRLEN(firstline);
  2133.     }
  2134.  
  2135.     if (oap->op_type == OP_APPEND)
  2136.     {
  2137.     if (oap->block_mode && curwin->w_cursor.coladd == 0)
  2138.     {
  2139.         /* this lil bit if code adapted from nv_append() */
  2140.         curwin->w_set_curswant = TRUE;
  2141.         while (inc_cursor() == 0
  2142.             && (curwin->w_cursor.col < bd.textcol + bd.textlen))
  2143.         ;
  2144.         if (bd.is_short && !bd.is_MAX)
  2145.         {
  2146.         /* First line was too short, make it longer and adjust the
  2147.          * values in "bd". */
  2148.         for (i = 0; i < bd.endspaces; ++i)
  2149.             ins_char(' ');
  2150.         bd.textlen += bd.endspaces;
  2151.         }
  2152.     }
  2153.     else
  2154.     {
  2155.         curwin->w_cursor = oap->end;
  2156.  
  2157.         /* Works just like an 'i'nsert on the next character. */
  2158.         if (!lineempty(curwin->w_cursor.lnum)
  2159.             && oap->start_vcol != oap->end_vcol)
  2160.         inc_cursor();
  2161.     }
  2162.     }
  2163.  
  2164.     edit(NUL, FALSE, (linenr_T)count1);
  2165.  
  2166.     /* if user has moved off this line, we don't know what to do, so do
  2167.      * nothing */
  2168.     if (curwin->w_cursor.lnum != oap->start.lnum)
  2169.     return;
  2170.  
  2171.  
  2172.     if (oap->block_mode)
  2173.     {
  2174.     struct block_def    bd2;
  2175.  
  2176.     /*
  2177.      * Spaces and tabs in the indent may have changed to other spaces and
  2178.      * tabs.  Get the starting column again and correct the lenght.
  2179.      * Don't do this when "$" used, end-of-line will have changed.
  2180.      */
  2181.     block_prep(oap, &bd2, oap->start.lnum, TRUE);
  2182.     if (!bd.is_MAX || bd2.textlen < bd.textlen)
  2183.     {
  2184.         if (oap->op_type == OP_APPEND)
  2185.         {
  2186.         pre_textlen += bd2.textlen - bd.textlen;
  2187.         if (bd2.endspaces)
  2188.             --bd2.textlen;
  2189.         }
  2190.         bd.textcol = bd2.textcol;
  2191.         bd.textlen = bd2.textlen;
  2192.     }
  2193.  
  2194.     /*
  2195.      * Subsequent calls to ml_get() flush the firstline data - take a
  2196.      * copy of the required string.
  2197.      */
  2198.     firstline = ml_get(oap->start.lnum) + bd.textcol;
  2199.     if (oap->op_type == OP_APPEND)
  2200.         firstline += bd.textlen;
  2201.     if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
  2202.     {
  2203.         ins_text = vim_strnsave(firstline, (int)ins_len);
  2204.         if (ins_text != NULL)
  2205.         {
  2206.         /* block handled here */
  2207.         block_insert(oap, ins_text, (oap->op_type == OP_INSERT), &bd);
  2208.  
  2209.         curwin->w_cursor.col = oap->start.col;
  2210.         check_cursor();
  2211.         }
  2212.         vim_free(ins_text);
  2213.     }
  2214.     }
  2215.  
  2216. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  2217.     if (oap->motion_type == MLINE)
  2218.     fix_indent();
  2219. #endif
  2220. }
  2221. #endif
  2222.  
  2223. /*
  2224.  * op_change - handle a change operation
  2225.  *
  2226.  * return TRUE if edit() returns because of a CTRL-O command
  2227.  */
  2228.     int
  2229. op_change(oap)
  2230.     oparg_T    *oap;
  2231. {
  2232.     colnr_T        l;
  2233.     int            retval;
  2234. #ifdef FEAT_VISUALEXTRA
  2235.     long        offset;
  2236.     linenr_T        linenr;
  2237.     long        ins_len, pre_textlen = 0;
  2238.     char_u        *firstline;
  2239.     char_u        *ins_text, *newp, *oldp;
  2240.     struct block_def    bd;
  2241. #endif
  2242.  
  2243.     l = oap->start.col;
  2244.     if (oap->motion_type == MLINE)
  2245.     {
  2246.     l = 0;
  2247. #ifdef FEAT_SMARTINDENT
  2248.     if (!p_paste && curbuf->b_p_si
  2249. # ifdef FEAT_CINDENT
  2250.         && !curbuf->b_p_cin
  2251. # endif
  2252.         )
  2253.         can_si = TRUE;    /* It's like opening a new line, do si */
  2254. #endif
  2255.     }
  2256.  
  2257.     /* First delete the text in the region.  In an empty buffer only need to
  2258.      * save for undo */
  2259.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  2260.     {
  2261.     if (u_save_cursor() == FAIL)
  2262.         return FALSE;
  2263.     }
  2264.     else if (op_delete(oap) == FAIL)
  2265.     return FALSE;
  2266.  
  2267.     if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum)
  2268.                              && !virtual_active())
  2269.     inc_cursor();
  2270.  
  2271. #ifdef FEAT_VISUALEXTRA
  2272.     /* check for still on same line (<CR> in inserted text meaningless) */
  2273.     /* skip blank lines too */
  2274.     if (oap->block_mode)
  2275.     {
  2276.     firstline = ml_get(oap->start.lnum);
  2277.     pre_textlen = (long)STRLEN(firstline);
  2278.     block_prep(oap, &bd, oap->start.lnum, TRUE);
  2279.     }
  2280. #endif
  2281.  
  2282. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  2283.     if (oap->motion_type == MLINE)
  2284.     fix_indent();
  2285. #endif
  2286.  
  2287.     retval = edit(NUL, FALSE, (linenr_T)1);
  2288.  
  2289. #ifdef FEAT_VISUALEXTRA
  2290.     /*
  2291.      * In Visual block mode, handle copying the next text to all lines of the
  2292.      * block.
  2293.      */
  2294.     if (oap->block_mode && oap->start.lnum != oap->end.lnum)
  2295.     {
  2296.     firstline = ml_get(oap->start.lnum);
  2297.     /*
  2298.      * Subsequent calls to ml_get() flush the firstline data - take a
  2299.      * copy of the required bit.
  2300.      */
  2301.     if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
  2302.     {
  2303.         if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != 0)
  2304.         {
  2305.         /* put cursor at end of changed text */
  2306.         curwin->w_cursor = oap->end;
  2307.  
  2308.         STRNCPY(ins_text, firstline + bd.textcol, ins_len);
  2309.         *(ins_text + ins_len) = NUL;
  2310.         for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum;
  2311.                                      linenr++)
  2312.         {
  2313.             block_prep(oap, &bd, linenr, TRUE);
  2314.             if (!bd.is_short)
  2315.             {
  2316.             oldp = ml_get(linenr);
  2317.             newp = alloc_check((unsigned)(STRLEN(oldp)
  2318.                                   + ins_len + 1));
  2319.             if (newp == NULL)
  2320.                 continue;
  2321.             /* copy up to block start */
  2322.             mch_memmove(newp, oldp, (size_t)bd.textcol);
  2323.             for (offset = 0; offset < ins_len; offset++)
  2324.                 *(newp + bd.textcol + offset) = *(ins_text
  2325.                                     + offset);
  2326.             oldp += bd.textcol;
  2327.             mch_memmove(newp + bd.textcol + offset, oldp,
  2328.                                 STRLEN(oldp) + 1);
  2329.             ml_replace(linenr, newp, FALSE);
  2330.             if (linenr == oap->end.lnum)
  2331.                 curwin->w_cursor.col = bd.textcol + ins_len - 1;
  2332.             }
  2333.         }
  2334.         curwin->w_cursor.col = oap->start.col;
  2335.         check_cursor();
  2336.  
  2337.         changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
  2338.         }
  2339.         vim_free(ins_text);
  2340.     }
  2341.     }
  2342. #endif
  2343.  
  2344.     return retval;
  2345. }
  2346.  
  2347. /*
  2348.  * set all the yank registers to empty (called from main())
  2349.  */
  2350.     void
  2351. init_yank()
  2352. {
  2353.     int        i;
  2354.  
  2355.     for (i = 0; i < NUM_REGISTERS; ++i)
  2356.     y_regs[i].y_array = NULL;
  2357. }
  2358.  
  2359. /*
  2360.  * Free "n" lines from the current yank register.
  2361.  * Called for normal freeing and in case of error.
  2362.  */
  2363.     static void
  2364. free_yank(n)
  2365.     long    n;
  2366. {
  2367.     if (y_current->y_array != NULL)
  2368.     {
  2369.     long        i;
  2370.  
  2371.     for (i = n; --i >= 0; )
  2372.     {
  2373. #ifdef AMIGA        /* only for very slow machines */
  2374.         if ((i & 1023) == 1023)  /* this may take a while */
  2375.         {
  2376.         /*
  2377.          * This message should never cause a hit-return message.
  2378.          * Overwrite this message with any next message.
  2379.          */
  2380.         ++no_wait_return;
  2381.         smsg((char_u *)_("freeing %ld lines"), i + 1);
  2382.         --no_wait_return;
  2383.         msg_didout = FALSE;
  2384.         msg_col = 0;
  2385.         }
  2386. #endif
  2387.         vim_free(y_current->y_array[i]);
  2388.     }
  2389.     vim_free(y_current->y_array);
  2390.     y_current->y_array = NULL;
  2391. #ifdef AMIGA
  2392.     if (n >= 1000)
  2393.         MSG("");
  2394. #endif
  2395.     }
  2396. }
  2397.  
  2398.     static void
  2399. free_yank_all()
  2400. {
  2401.     free_yank(y_current->y_size);
  2402. }
  2403.  
  2404. /*
  2405.  * Yank the text between curwin->w_cursor and startpos into a yank register.
  2406.  * If we are to append (uppercase register), we first yank into a new yank
  2407.  * register and then concatenate the old and the new one (so we keep the old
  2408.  * one in case of out-of-memory).
  2409.  *
  2410.  * return FAIL for failure, OK otherwise
  2411.  */
  2412.     int
  2413. op_yank(oap, deleting, mess)
  2414.     oparg_T   *oap;
  2415.     int        deleting;
  2416.     int        mess;
  2417. {
  2418.     long        y_idx;        /* index in y_array[] */
  2419.     struct yankreg    *curr;        /* copy of y_current */
  2420.     struct yankreg    newreg;        /* new yank register when appending */
  2421.     char_u        **new_ptr;
  2422.     linenr_T        lnum;        /* current line number */
  2423.     long        j;
  2424.     int            yanktype = oap->motion_type;
  2425.     long        yanklines = oap->line_count;
  2426.     linenr_T        yankendlnum = oap->end.lnum;
  2427.     char_u        *p;
  2428.     char_u        *pnew;
  2429.     struct block_def    bd;
  2430.  
  2431.                     /* check for read-only register */
  2432.     if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
  2433.     {
  2434.     beep_flush();
  2435.     return FAIL;
  2436.     }
  2437.     if (oap->regname == '_')        /* black hole: nothing to do */
  2438.     return OK;
  2439.  
  2440. #ifdef FEAT_CLIPBOARD
  2441.     if (!clip_star.available && oap->regname == '*')
  2442.     oap->regname = 0;
  2443.     else if (!clip_plus.available && oap->regname == '+')
  2444.     oap->regname = 0;
  2445. #endif
  2446.  
  2447.     if (!deleting)            /* op_delete() already set y_current */
  2448.     get_yank_register(oap->regname, TRUE);
  2449.  
  2450.     curr = y_current;
  2451.                     /* append to existing contents */
  2452.     if (y_append && y_current->y_array != NULL)
  2453.     y_current = &newreg;
  2454.     else
  2455.     free_yank_all();        /* free previously yanked lines */
  2456.  
  2457. /*
  2458.  * If the cursor was in column 1 before and after the movement, and the
  2459.  * operator is not inclusive, the yank is always linewise.
  2460.  */
  2461.     if (       oap->motion_type == MCHAR
  2462.         && oap->start.col == 0
  2463.         && !oap->inclusive
  2464. #ifdef FEAT_VISUAL
  2465.         && (!oap->is_VIsual || *p_sel == 'o')
  2466. #endif
  2467.         && oap->end.col == 0
  2468.         && yanklines > 1)
  2469.     {
  2470.     yanktype = MLINE;
  2471.     --yankendlnum;
  2472.     --yanklines;
  2473.     }
  2474.  
  2475.     y_current->y_size = yanklines;
  2476.     y_current->y_type = yanktype;   /* set the yank register type */
  2477.     y_current->y_width = 0;
  2478.     y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) *
  2479.                                 yanklines), TRUE);
  2480.  
  2481.     if (y_current->y_array == NULL)
  2482.     {
  2483.     y_current = curr;
  2484.     return FAIL;
  2485.     }
  2486.  
  2487.     y_idx = 0;
  2488.     lnum = oap->start.lnum;
  2489.  
  2490.     if (oap->block_mode)
  2491.     {
  2492.     /* Visual block mode */
  2493.     y_current->y_type = MBLOCK;        /* set the yank register type */
  2494.     y_current->y_width = oap->end_vcol - oap->start_vcol;
  2495.  
  2496.     if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
  2497.         y_current->y_width--;
  2498.     }
  2499.  
  2500.     for ( ; lnum <= yankendlnum; lnum++, y_idx++)
  2501.     {
  2502.     switch (y_current->y_type)
  2503.     {
  2504.         case MBLOCK:
  2505.         block_prep(oap, &bd, lnum, FALSE);
  2506. copyline:
  2507.         if ((pnew = alloc(bd.startspaces + bd.endspaces
  2508.                            + bd.textlen + 1)) == NULL)
  2509.         {
  2510. fail:             /* free the allocated lines */
  2511.             free_yank(y_idx + 1);
  2512.             y_current = curr;
  2513.             return FAIL;
  2514.         }
  2515.         y_current->y_array[y_idx] = pnew;
  2516.         copy_spaces(pnew, (size_t)bd.startspaces);
  2517.         pnew += bd.startspaces;
  2518.         mch_memmove(pnew, bd.textstart, (size_t)bd.textlen);
  2519.         pnew += bd.textlen;
  2520.         copy_spaces(pnew, (size_t)bd.endspaces);
  2521.         pnew += bd.endspaces;
  2522.         *pnew = NUL;
  2523.         break;
  2524.  
  2525.         case MLINE:
  2526.         if ((y_current->y_array[y_idx] =
  2527.                 vim_strsave(ml_get(lnum))) == NULL)
  2528.             goto fail;
  2529.         break;
  2530.  
  2531.         case MCHAR:
  2532.         {
  2533.             colnr_T startcol = 0, endcol = MAXCOL;
  2534. #ifdef FEAT_VIRTUALEDIT
  2535.             int is_oneChar = FALSE;
  2536.             colnr_T cs, ce;
  2537. #endif
  2538.             p = ml_get(lnum);
  2539.             bd.startspaces = 0;
  2540.             bd.endspaces = 0;
  2541.  
  2542.             if (lnum == oap->start.lnum)
  2543.             {
  2544.             startcol = oap->start.col;
  2545. #ifdef FEAT_VIRTUALEDIT
  2546.             if (virtual_active())
  2547.             {
  2548.                 getvcol(curwin, &oap->start, &cs, NUL, &ce);
  2549.                 if (ce != cs && oap->start.coladd > 0)
  2550.                 {
  2551.                 /* Part of a tab selected -- but don't
  2552.                  * double-count it. */
  2553.                 bd.startspaces = (ce - cs + 1)
  2554.                               - oap->start.coladd;
  2555.                 startcol++;
  2556.                 }
  2557.             }
  2558. #endif
  2559.             }
  2560.  
  2561.             if (lnum == oap->end.lnum)
  2562.             {
  2563.             endcol = oap->end.col;
  2564. #ifdef FEAT_VIRTUALEDIT
  2565.             if (virtual_active())
  2566.             {
  2567.                 getvcol(curwin, &oap->end, &cs, NUL, &ce);
  2568.                 if (p[endcol] == NUL || cs + oap->end.coladd < ce)
  2569.                 {
  2570.                 /* Special case: inside a single char */
  2571.                 if (oap->start.lnum == oap->end.lnum
  2572.                         && oap->start.col == oap->end.col)
  2573.                 {
  2574.                     is_oneChar = TRUE;
  2575.                     bd.startspaces = oap->end.coladd
  2576.                      - oap->start.coladd + oap->inclusive;
  2577.                     endcol = startcol;
  2578.                 }
  2579.                 else
  2580.                 {
  2581.                     bd.endspaces = oap->end.coladd
  2582.                                  + oap->inclusive;
  2583.                     endcol -= oap->inclusive;
  2584.                 }
  2585.                 }
  2586.             }
  2587. #endif
  2588.             }
  2589.             if (startcol > endcol
  2590. #ifdef FEAT_VIRTUALEDIT
  2591.                 || is_oneChar
  2592. #endif
  2593.                 )
  2594.             bd.textlen = 0;
  2595.             else
  2596.             {
  2597.             if (endcol == MAXCOL)
  2598.                 endcol = STRLEN(p);
  2599.             bd.textlen = endcol - startcol + oap->inclusive;
  2600.             }
  2601.             bd.textstart = p + startcol;
  2602.             goto copyline;
  2603.         }
  2604.         /* NOTREACHED */
  2605.     }
  2606.     }
  2607.  
  2608.     if (curr != y_current)    /* append the new block to the old block */
  2609.     {
  2610.     new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) *
  2611.                    (curr->y_size + y_current->y_size)), TRUE);
  2612.     if (new_ptr == NULL)
  2613.         goto fail;
  2614.     for (j = 0; j < curr->y_size; ++j)
  2615.         new_ptr[j] = curr->y_array[j];
  2616.     vim_free(curr->y_array);
  2617.     curr->y_array = new_ptr;
  2618.  
  2619.     if (yanktype == MLINE)    /* MLINE overrides MCHAR and MBLOCK */
  2620.         curr->y_type = MLINE;
  2621.  
  2622.     /* concatenate the last line of the old block with the first line of
  2623.      * the new block */
  2624.     if (curr->y_type == MCHAR)
  2625.     {
  2626.         pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1])
  2627.                   + STRLEN(y_current->y_array[0]) + 1), TRUE);
  2628.         if (pnew == NULL)
  2629.         {
  2630.             y_idx = y_current->y_size - 1;
  2631.             goto fail;
  2632.         }
  2633.         STRCPY(pnew, curr->y_array[--j]);
  2634.         STRCAT(pnew, y_current->y_array[0]);
  2635.         vim_free(curr->y_array[j]);
  2636.         vim_free(y_current->y_array[0]);
  2637.         curr->y_array[j++] = pnew;
  2638.         y_idx = 1;
  2639.     }
  2640.     else
  2641.         y_idx = 0;
  2642.     while (y_idx < y_current->y_size)
  2643.         curr->y_array[j++] = y_current->y_array[y_idx++];
  2644.     curr->y_size = j;
  2645.     vim_free(y_current->y_array);
  2646.     y_current = curr;
  2647.     }
  2648.     if (mess)            /* Display message about yank? */
  2649.     {
  2650.     if (yanktype == MCHAR && !oap->block_mode && yanklines == 1)
  2651.         yanklines = 0;
  2652.     /* Some versions of Vi use ">=" here, some don't...  */
  2653.     if (yanklines > p_report)
  2654.     {
  2655.         /* redisplay now, so message is not deleted */
  2656.         update_topline_redraw();
  2657.         if (yanklines == 1)
  2658.         MSG(_("1 line yanked"));
  2659.         else
  2660.         smsg((char_u *)_("%ld lines yanked"), yanklines);
  2661.     }
  2662.     }
  2663.  
  2664.     /*
  2665.      * Set "'[" and "']" marks.
  2666.      */
  2667.     curbuf->b_op_start = oap->start;
  2668.     curbuf->b_op_end = oap->end;
  2669.  
  2670. #ifdef FEAT_CLIPBOARD
  2671.     /*
  2672.      * If we were yanking to the '*' register, send result to clipboard.
  2673.      * If no register was specified, and "unnamed" in 'clipboard', make a copy
  2674.      * to the '*' register.
  2675.      */
  2676.     if (clip_star.available
  2677.         && (curr == &(y_regs[STAR_REGISTER])
  2678.         || (!deleting && oap->regname == 0 && clip_unnamed)))
  2679.     {
  2680.     if (curr != &(y_regs[STAR_REGISTER]))
  2681.         /* Copy the text from register 0 to the clipboard register. */
  2682.         copy_yank_reg(&(y_regs[STAR_REGISTER]));
  2683.  
  2684.     clip_own_selection(&clip_star);
  2685.     clip_gen_set_selection(&clip_star);
  2686.     }
  2687.  
  2688. # ifdef FEAT_X11
  2689.     /*
  2690.      * If we were yanking to the '+' register, send result to selection.
  2691.      * Also copy to the '*' register, in case auto-select is off.
  2692.      */
  2693.     else if (clip_plus.available && curr == &(y_regs[PLUS_REGISTER]))
  2694.     {
  2695.     /* No need to copy to * register upon 'unnamed' now - see below */
  2696.     clip_own_selection(&clip_plus);
  2697.     clip_gen_set_selection(&clip_plus);
  2698.     if (!clip_isautosel())
  2699.     {
  2700.         copy_yank_reg(&(y_regs[STAR_REGISTER]));
  2701.         clip_own_selection(&clip_star);
  2702.         clip_gen_set_selection(&clip_star);
  2703.     }
  2704.     }
  2705. # endif
  2706. #endif
  2707.  
  2708.     return OK;
  2709. }
  2710.  
  2711. #ifdef FEAT_CLIPBOARD
  2712. /*
  2713.  * Make a copy of the y_current register to register "reg".
  2714.  */
  2715.     static void
  2716. copy_yank_reg(reg)
  2717.     struct yankreg *reg;
  2718. {
  2719.     struct yankreg    *curr = y_current;
  2720.     long        j;
  2721.  
  2722.     y_current = reg;
  2723.     free_yank_all();
  2724.     *y_current = *curr;
  2725.     y_current->y_array = (char_u **)lalloc_clear(
  2726.             (long_u)(sizeof(char_u *) * y_current->y_size), TRUE);
  2727.     if (y_current->y_array == NULL)
  2728.     y_current->y_size = 0;
  2729.     else
  2730.     for (j = 0; j < y_current->y_size; ++j)
  2731.         if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
  2732.         {
  2733.         free_yank(j);
  2734.         y_current->y_size = 0;
  2735.         break;
  2736.         }
  2737.     y_current = curr;
  2738. }
  2739. #endif
  2740.  
  2741. /*
  2742.  * put contents of register "regname" into the text
  2743.  * For ":put" command count == -1.
  2744.  * flags: PUT_FIXINDENT    make indent look nice
  2745.  *      PUT_CURSEND    leave cursor after end of new text
  2746.  */
  2747.     void
  2748. do_put(regname, dir, count, flags)
  2749.     int        regname;
  2750.     int        dir;        /* BACKWARD for 'P', FORWARD for 'p' */
  2751.     long    count;
  2752.     int        flags;
  2753. {
  2754.     char_u    *ptr;
  2755.     char_u    *newp, *oldp;
  2756.     int        yanklen;
  2757.     int        oldlen;
  2758.     int        totlen = 0;        /* init for gcc */
  2759.     linenr_T    lnum;
  2760.     colnr_T    col;
  2761.     long    i;            /* index in y_array[] */
  2762.     int        y_type;
  2763.     long    y_size;
  2764.     long    y_width = 0;
  2765.     char_u    **y_array = NULL;
  2766.     long    nr_lines = 0;
  2767.     colnr_T    vcol;
  2768.     int        delcount;
  2769.     int        incr = 0;
  2770.     long    j;
  2771.     pos_T    new_cursor;
  2772.     int        indent;
  2773.     int        orig_indent = 0;    /* init for gcc */
  2774.     int        indent_diff = 0;    /* init for gcc */
  2775.     int        first_indent = TRUE;
  2776.     int        lendiff = 0;
  2777.     pos_T    old_pos;
  2778.     struct block_def bd;
  2779.     char_u    *insert_string = NULL;
  2780.     int        allocated = FALSE;
  2781. #ifdef FEAT_MBYTE
  2782.     int        bytelen = 0;
  2783. #endif
  2784.     long    cnt;
  2785.  
  2786. #ifdef FEAT_CLIPBOARD
  2787.     /* If no register specified, and "unnamed" in 'clipboard', use + register */
  2788.     if (regname == 0 && clip_unnamed)
  2789.     regname = '*';
  2790.     if (regname == '*')
  2791.     {
  2792.     if (!clip_star.available)
  2793.         regname = 0;
  2794.     else
  2795.         clip_get_selection(&clip_star);
  2796.     }
  2797.     else if (regname == '+')
  2798.     {
  2799.     if (!clip_plus.available)
  2800.         regname = 0;
  2801.     else
  2802.         clip_get_selection(&clip_plus);
  2803.     }
  2804. #endif
  2805.  
  2806.     if (flags & PUT_FIXINDENT)
  2807.     orig_indent = get_indent();
  2808.  
  2809.     curbuf->b_op_start = curwin->w_cursor;    /* default for '[ mark */
  2810.     if (dir == FORWARD)
  2811.     {
  2812.     /* move to the start of the next (multi-byte) character */
  2813. #ifdef FEAT_MBYTE
  2814.     if (has_mbyte)
  2815.     {
  2816.         bytelen = (*mb_ptr2len_check)(ml_get_cursor());
  2817.         curbuf->b_op_start.col += bytelen;
  2818.     }
  2819.     else
  2820. #endif
  2821.         curbuf->b_op_start.col++;
  2822.     }
  2823.  
  2824.     curbuf->b_op_end = curwin->w_cursor;    /* default for '] mark */
  2825.  
  2826.     /*
  2827.      * Using inserted text works differently, because the register includes
  2828.      * special characters (newlines, etc.).
  2829.      */
  2830.     if (regname == '.')
  2831.     {
  2832.     (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
  2833.                     (count == -1 ? 'O' : 'i')), count, FALSE);
  2834.     /* Putting the text is done later, so can't really move the cursor to
  2835.      * the nex character.  Use "l" to simulate it. */
  2836.     if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
  2837.         stuffcharReadbuff('l');
  2838.     return;
  2839.     }
  2840.  
  2841.     /*
  2842.      * For special registers '%' (file name), '#' (alternate file name) and
  2843.      * ':' (last command line), etc. we have to create a fake yank register.
  2844.      */
  2845.     if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
  2846.     {
  2847.     if (insert_string == NULL)
  2848.         return;
  2849.     }
  2850.  
  2851.     if (insert_string != NULL)
  2852.     {
  2853.     y_type = MCHAR;
  2854. #ifdef FEAT_EVAL
  2855.     if (regname == '=')
  2856.     {
  2857.         /* For the = register we need to split the string at NL
  2858.          * characters. */
  2859.         /* Loop twice: count the number of lines and save them. */
  2860.         for (;;)
  2861.         {
  2862.         y_size = 0;
  2863.         ptr = insert_string;
  2864.         while (ptr != NULL)
  2865.         {
  2866.             if (y_array != NULL)
  2867.             y_array[y_size] = ptr;
  2868.             ++y_size;
  2869.             ptr = vim_strchr(ptr, '\n');
  2870.             if (ptr != NULL)
  2871.             {
  2872.             if (y_array != NULL)
  2873.                 *ptr = NUL;
  2874.             ++ptr;
  2875.             /* A trailing '\n' makes the string linewise */
  2876.             if (*ptr == NUL)
  2877.             {
  2878.                 y_type = MLINE;
  2879.                 break;
  2880.             }
  2881.             }
  2882.         }
  2883.         if (y_array != NULL)
  2884.             break;
  2885.         y_array = (char_u **)alloc((unsigned)
  2886.                          (y_size * sizeof(char_u *)));
  2887.         if (y_array == NULL)
  2888.             goto end;
  2889.         }
  2890.     }
  2891.     else
  2892. #endif
  2893.     {
  2894.         y_size = 1;        /* use fake one-line yank register */
  2895.         y_array = &insert_string;
  2896.     }
  2897.     }
  2898.     else
  2899.     {
  2900.     get_yank_register(regname, FALSE);
  2901.  
  2902.     y_type = y_current->y_type;
  2903.     y_width = y_current->y_width;
  2904.     y_size = y_current->y_size;
  2905.     y_array = y_current->y_array;
  2906.     }
  2907.  
  2908.     if (count == -1)        /* :put command */
  2909.     {
  2910.     y_type = MLINE;
  2911.     count = 1;
  2912.     }
  2913.  
  2914.     if (y_size == 0 || y_array == NULL)
  2915.     {
  2916.     EMSG2(_("E353: Nothing in register %s"),
  2917.           regname == 0 ? (char_u *)"\"" : transchar(regname));
  2918.     goto end;
  2919.     }
  2920.  
  2921.     if (y_type == MBLOCK)
  2922.     {
  2923.     lnum = curwin->w_cursor.lnum + y_size + 1;
  2924.     if (lnum > curbuf->b_ml.ml_line_count)
  2925.         lnum = curbuf->b_ml.ml_line_count + 1;
  2926.     if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
  2927.         goto end;
  2928.     }
  2929.     else if (y_type == MLINE)
  2930.     {
  2931.     lnum = curwin->w_cursor.lnum;
  2932. #ifdef FEAT_FOLDING
  2933.     /* Correct line number for closed fold.  Don't move the cursor yet,
  2934.      * u_save() uses it. */
  2935.     if (dir == BACKWARD)
  2936.         (void)hasFolding(lnum, &lnum, NULL);
  2937.     else
  2938.         (void)hasFolding(lnum, NULL, &lnum);
  2939. #endif
  2940.     if (dir == FORWARD)
  2941.         ++lnum;
  2942.     if (u_save(lnum - 1, lnum) == FAIL)
  2943.         goto end;
  2944. #ifdef FEAT_FOLDING
  2945.     if (dir == FORWARD)
  2946.         curwin->w_cursor.lnum = lnum - 1;
  2947.     else
  2948.         curwin->w_cursor.lnum = lnum;
  2949. #endif
  2950.     }
  2951.     else if (u_save_cursor() == FAIL)
  2952.     goto end;
  2953.  
  2954.     yanklen = (int)STRLEN(y_array[0]);
  2955.  
  2956. #ifdef FEAT_VIRTUALEDIT
  2957.     if (ve_flags == VE_ALL && y_type == MCHAR)
  2958.     {
  2959.     if (gchar_cursor() == TAB)
  2960.     {
  2961.         /* Don't need to insert spaces when "p" on the last position of a
  2962.          * tab or "P" on the first position. */
  2963.         if (dir == FORWARD
  2964.             ? (int)curwin->w_cursor.coladd < curbuf->b_p_ts - 1
  2965.                         : curwin->w_cursor.coladd > 0)
  2966.         coladvance_force(getviscol());
  2967.         else
  2968.         curwin->w_cursor.coladd = 0;
  2969.     }
  2970.     else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
  2971.         coladvance_force(getviscol() + (dir == FORWARD));
  2972.     }
  2973. #endif
  2974.  
  2975.     lnum = curwin->w_cursor.lnum;
  2976.     col = curwin->w_cursor.col;
  2977.  
  2978.     /*
  2979.      * Block mode
  2980.      */
  2981.     if (y_type == MBLOCK)
  2982.     {
  2983.     char    c = gchar_cursor();
  2984.     colnr_T    endcol2 = 0;
  2985.  
  2986.     if (dir == FORWARD && c != NUL)
  2987.     {
  2988. #ifdef FEAT_VIRTUALEDIT
  2989.         if (ve_flags == VE_ALL)
  2990.         getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
  2991.         else
  2992. #endif
  2993.         getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
  2994.  
  2995. #ifdef FEAT_MBYTE
  2996.         if (has_mbyte)
  2997.         /* move to start of next multi-byte character */
  2998.         curwin->w_cursor.col += bytelen;
  2999.         else
  3000. #endif
  3001. #ifdef FEAT_VIRTUALEDIT
  3002.         if (c != TAB || ve_flags != VE_ALL)
  3003. #endif
  3004.         ++curwin->w_cursor.col;
  3005.         ++col;
  3006.     }
  3007.     else
  3008.         getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
  3009.  
  3010. #ifdef FEAT_VIRTUALEDIT
  3011.     col += curwin->w_cursor.coladd;
  3012.     if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0)
  3013.     {
  3014.         if (dir == FORWARD && c == NUL)
  3015.         ++col;
  3016.         if (dir != FORWARD && c != NUL)
  3017.         ++curwin->w_cursor.col;
  3018.         if (c == TAB)
  3019.         {
  3020.         if (dir == BACKWARD && curwin->w_cursor.col)
  3021.             curwin->w_cursor.col--;
  3022.         if (dir == FORWARD && col - 1 == endcol2)
  3023.             curwin->w_cursor.col++;
  3024.         }
  3025.     }
  3026.     curwin->w_cursor.coladd = 0;
  3027. #endif
  3028.     for (i = 0; i < y_size; ++i)
  3029.     {
  3030.         int spaces;
  3031.         char shortline;
  3032.  
  3033.         bd.startspaces = 0;
  3034.         bd.endspaces = 0;
  3035.         bd.textcol = 0;
  3036.         vcol = 0;
  3037.         delcount = 0;
  3038.  
  3039.         /* add a new line */
  3040.         if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  3041.         {
  3042.         if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
  3043.                            (colnr_T)1, FALSE) == FAIL)
  3044.             break;
  3045.         ++nr_lines;
  3046.         }
  3047.         /* get the old line and advance to the position to insert at */
  3048.         oldp = ml_get_curline();
  3049.         oldlen = (int)STRLEN(oldp);
  3050.         for (ptr = oldp; vcol < col && *ptr; )
  3051.         {
  3052.         /* Count a tab for what it's worth (if list mode not on) */
  3053.         incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol);
  3054.         vcol += incr;
  3055.         }
  3056.         bd.textcol = (colnr_T)(ptr - oldp);
  3057.  
  3058.         shortline = (vcol < col) || (vcol == col && !*ptr) ;
  3059.  
  3060.         if (vcol < col) /* line too short, padd with spaces */
  3061.         bd.startspaces = col - vcol;
  3062.         else if (vcol > col)
  3063.         {
  3064.         bd.endspaces = vcol - col;
  3065.         bd.startspaces = incr - bd.endspaces;
  3066.         --bd.textcol;
  3067.         delcount = 1;
  3068. #ifdef FEAT_MBYTE
  3069.         if (has_mbyte)
  3070.             bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
  3071. #endif
  3072.         if (oldp[bd.textcol] != TAB)
  3073.         {
  3074.             /* Only a Tab can be split into spaces.  Other
  3075.              * characters will have to be moved to after the
  3076.              * block, causing misalignment. */
  3077.             delcount = 0;
  3078.             bd.endspaces = 0;
  3079.         }
  3080.         }
  3081.  
  3082.         yanklen = (int)STRLEN(y_array[i]);
  3083.  
  3084.         /* calculate number of spaces required to fill right side of block*/
  3085.         spaces = y_width + 1;
  3086.         for (j = 0; j < yanklen; j++)
  3087.         spaces -= lbr_chartabsize(&y_array[i][j], 0);
  3088.         if (spaces < 0)
  3089.         spaces = 0;
  3090.  
  3091.         /* insert the new text */
  3092.         totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
  3093.         newp = alloc_check((unsigned)totlen + oldlen + 1);
  3094.         if (newp == NULL)
  3095.         break;
  3096.         /* copy part up to cursor to new line */
  3097.         ptr = newp;
  3098.         mch_memmove(ptr, oldp, (size_t)bd.textcol);
  3099.         ptr += bd.textcol;
  3100.         /* may insert some spaces before the new text */
  3101.         copy_spaces(ptr, (size_t)bd.startspaces);
  3102.         ptr += bd.startspaces;
  3103.         /* insert the new text */
  3104.         for (j = 0; j < count; ++j)
  3105.         {
  3106.         mch_memmove(ptr, y_array[i], (size_t)yanklen);
  3107.         ptr += yanklen;
  3108.  
  3109.         /* insert block's trailing spaces only if there's text behind */
  3110.         if ((j < count - 1 || !shortline) && spaces)
  3111.         {
  3112.             copy_spaces(ptr, (size_t)spaces);
  3113.             ptr += spaces;
  3114.         }
  3115.         }
  3116.         /* may insert some spaces after the new text */
  3117.         copy_spaces(ptr, (size_t)bd.endspaces);
  3118.         ptr += bd.endspaces;
  3119.         /* move the text after the cursor to the end of the line. */
  3120.         mch_memmove(ptr, oldp + bd.textcol + delcount,
  3121.                 (size_t)(oldlen - bd.textcol - delcount + 1));
  3122.         ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  3123.  
  3124.         ++curwin->w_cursor.lnum;
  3125.         if (i == 0)
  3126.         curwin->w_cursor.col += bd.startspaces;
  3127.     }
  3128.  
  3129.     changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
  3130.  
  3131.     /* adjust '] mark */
  3132.     curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
  3133.     curbuf->b_op_end.col = bd.textcol + totlen - 1;
  3134.     if (flags & PUT_CURSEND)
  3135.     {
  3136.         curwin->w_cursor = curbuf->b_op_end;
  3137.         curwin->w_cursor.col++;
  3138.     }
  3139.     else
  3140.         curwin->w_cursor.lnum = lnum;
  3141.     }
  3142.     else
  3143.     {
  3144.     /*
  3145.      * Character or Line mode
  3146.      */
  3147.     if (y_type == MCHAR)
  3148.     {
  3149.         /* if type is MCHAR, FORWARD is the same as BACKWARD on the next
  3150.          * char */
  3151.         if (dir == FORWARD && gchar_cursor() != NUL)
  3152.         {
  3153. #ifdef FEAT_MBYTE
  3154.         if (has_mbyte)
  3155.         {
  3156.             /* put it on the next of the multi-byte character. */
  3157.             col += bytelen;
  3158.             if (yanklen)
  3159.             {
  3160.             curwin->w_cursor.col += bytelen;
  3161.             curbuf->b_op_end.col += bytelen;
  3162.             }
  3163.         }
  3164.         else
  3165. #endif
  3166.         {
  3167.             ++col;
  3168.             if (yanklen)
  3169.             {
  3170.             ++curwin->w_cursor.col;
  3171.             ++curbuf->b_op_end.col;
  3172.             }
  3173.         }
  3174.         }
  3175.         new_cursor = curwin->w_cursor;
  3176.     }
  3177.     /*
  3178.      * Line mode: BACKWARD is the same as FORWARD on the previous line
  3179.      */
  3180.     else if (dir == BACKWARD)
  3181.         --lnum;
  3182.  
  3183.     /*
  3184.      * simple case: insert into current line
  3185.      */
  3186.     if (y_type == MCHAR && y_size == 1)
  3187.     {
  3188.         totlen = count * yanklen;
  3189.         if (totlen)
  3190.         {
  3191.         oldp = ml_get(lnum);
  3192.         newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
  3193.         if (newp == NULL)
  3194.             goto end;        /* alloc() will give error message */
  3195.         mch_memmove(newp, oldp, (size_t)col);
  3196.         ptr = newp + col;
  3197.         for (i = 0; i < count; ++i)
  3198.         {
  3199.             mch_memmove(ptr, y_array[0], (size_t)yanklen);
  3200.             ptr += yanklen;
  3201.         }
  3202.         mch_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
  3203.         ml_replace(lnum, newp, FALSE);
  3204.         /* Put cursor on last putted char. */
  3205.         curwin->w_cursor.col += (colnr_T)(totlen - 1);
  3206.         }
  3207.         curbuf->b_op_end = curwin->w_cursor;
  3208.         /* For "CTRL-O p" in Insert mode, put cursor after last char */
  3209.         if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
  3210.         ++curwin->w_cursor.col;
  3211.         changed_bytes(lnum, col);
  3212.     }
  3213.     else
  3214.     {
  3215.         /*
  3216.          * Insert at least one one.  When y_type is MCHAR, break the first
  3217.          * line in two.
  3218.          */
  3219.         for (cnt = 1; cnt <= count; ++cnt)
  3220.         {
  3221.         i = 0;
  3222.         if (y_type == MCHAR)
  3223.         {
  3224.             /*
  3225.              * Split the current line in two at the insert position.
  3226.              * First insert y_array[size - 1] in front of second line.
  3227.              * Then append y_array[0] to first line.
  3228.              */
  3229.             ptr = ml_get(lnum) + col;
  3230.             totlen = (int)STRLEN(y_array[y_size - 1]);
  3231.             newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
  3232.             if (newp == NULL)
  3233.             goto error;
  3234.             STRCPY(newp, y_array[y_size - 1]);
  3235.             STRCAT(newp, ptr);
  3236.             /* insert second line */
  3237.             ml_append(lnum, newp, (colnr_T)0, FALSE);
  3238.             vim_free(newp);
  3239.  
  3240.             oldp = ml_get(lnum);
  3241.             newp = alloc_check((unsigned)(col + yanklen + 1));
  3242.             if (newp == NULL)
  3243.             goto error;
  3244.                         /* copy first part of line */
  3245.             mch_memmove(newp, oldp, (size_t)col);
  3246.                         /* append to first line */
  3247.             mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
  3248.             ml_replace(lnum, newp, FALSE);
  3249.  
  3250.             curwin->w_cursor.lnum = lnum;
  3251.             i = 1;
  3252.         }
  3253.  
  3254.         while (i < y_size)
  3255.         {
  3256.             if ((y_type != MCHAR || i < y_size - 1)
  3257.                 && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
  3258.                                       == FAIL)
  3259.                 goto error;
  3260.             lnum++;
  3261.             i++;
  3262.             ++nr_lines;
  3263.             if (flags & PUT_FIXINDENT)
  3264.             {
  3265.             old_pos = curwin->w_cursor;
  3266.             curwin->w_cursor.lnum = lnum;
  3267.             ptr = ml_get(lnum);
  3268.             if (cnt == count && i == y_size - 1)
  3269.                 lendiff = (int)STRLEN(ptr);
  3270. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
  3271.             if (*ptr == '#' && preprocs_left())
  3272.                 indent = 0;     /* Leave # lines at start */
  3273.             else
  3274. #endif
  3275.                  if (*ptr == NUL)
  3276.                 indent = 0;     /* Ignore empty lines */
  3277.             else if (first_indent)
  3278.             {
  3279.                 indent_diff = orig_indent - get_indent();
  3280.                 indent = orig_indent;
  3281.                 first_indent = FALSE;
  3282.             }
  3283.             else if ((indent = get_indent() + indent_diff) < 0)
  3284.                 indent = 0;
  3285.             (void)set_indent(indent, 0);
  3286.             curwin->w_cursor = old_pos;
  3287.             /* remember how many chars were removed */
  3288.             if (cnt == count && i == y_size - 1)
  3289.                 lendiff -= (int)STRLEN(ml_get(lnum));
  3290.             }
  3291.         }
  3292.         }
  3293.  
  3294. error:
  3295.         /* Adjust marks. */
  3296.         if (y_type == MLINE)
  3297.         {
  3298.         curbuf->b_op_start.col = 0;
  3299.         if (dir == FORWARD)
  3300.         {
  3301. #ifdef FEAT_FOLDING
  3302.             /* a "p" inside a closed fold is like a "p" in the last
  3303.              * line of the fold */
  3304.             (void)hasFolding(curbuf->b_op_start.lnum, NULL,
  3305.                             &curbuf->b_op_start.lnum);
  3306. #endif
  3307.             curbuf->b_op_start.lnum++;
  3308.         }
  3309.         }
  3310.         mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
  3311.                          (linenr_T)MAXLNUM, nr_lines, 0L);
  3312.  
  3313.         /* note changed text for displaying and folding */
  3314.         if (y_type == MCHAR)
  3315.         changed_lines(curwin->w_cursor.lnum, col,
  3316.                      curwin->w_cursor.lnum + 1, nr_lines);
  3317.         else
  3318.         changed_lines(curbuf->b_op_start.lnum, 0,
  3319.                        curbuf->b_op_start.lnum, nr_lines);
  3320.  
  3321.         /* put '] mark at last inserted character */
  3322.         curbuf->b_op_end.lnum = lnum;
  3323.         /* correct length for change in indent */
  3324.         col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
  3325.         if (col > 1)
  3326.         curbuf->b_op_end.col = col - 1;
  3327.         else
  3328.         curbuf->b_op_end.col = 0;
  3329.  
  3330.         if (flags & PUT_CURSEND)
  3331.         {
  3332.         /* put cursor after inserted text */
  3333.         if (y_type == MLINE)
  3334.         {
  3335.             if (lnum >= curbuf->b_ml.ml_line_count)
  3336.             curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  3337.             else
  3338.             curwin->w_cursor.lnum = lnum + 1;
  3339.             curwin->w_cursor.col = 0;
  3340.         }
  3341.         else
  3342.         {
  3343.             curwin->w_cursor.lnum = lnum;
  3344.             curwin->w_cursor.col = col;
  3345.         }
  3346.         }
  3347.         else if (y_type == MLINE)
  3348.         {
  3349.         /* put cursor onfirst non-blank in first inserted line */
  3350.         curwin->w_cursor.col = 0;
  3351.         if (dir == FORWARD)
  3352.             ++curwin->w_cursor.lnum;
  3353.         beginline(BL_WHITE | BL_FIX);
  3354.         }
  3355.         else    /* put cursor on first inserted character */
  3356.         curwin->w_cursor = new_cursor;
  3357.     }
  3358.     }
  3359.  
  3360.     msgmore(nr_lines);
  3361.     curwin->w_set_curswant = TRUE;
  3362.  
  3363. end:
  3364.     if (allocated)
  3365.     {
  3366.     vim_free(insert_string);
  3367.     if (regname == '=')
  3368.         vim_free(y_array);
  3369.     }
  3370.     if ((flags & PUT_CURSEND)
  3371.         && gchar_cursor() == NUL
  3372.         && curwin->w_cursor.col
  3373.         && !(restart_edit || (State & INSERT)))
  3374.     --curwin->w_cursor.col;
  3375. }
  3376.  
  3377. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO)
  3378. /*
  3379.  * Return TRUE if lines starting with '#' should be left aligned.
  3380.  */
  3381.     int
  3382. preprocs_left()
  3383. {
  3384.     return
  3385. # ifdef FEAT_SMARTINDENT
  3386. #  ifdef FEAT_CINDENT
  3387.     (curbuf->b_p_si && !curbuf->b_p_cin) ||
  3388. #  else
  3389.     curbuf->b_p_si
  3390. #  endif
  3391. # endif
  3392. # ifdef FEAT_CINDENT
  3393.     (curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE))
  3394. # endif
  3395.     ;
  3396. }
  3397. #endif
  3398.  
  3399. /* Return the character name of the register with the given number */
  3400.     int
  3401. get_register_name(num)
  3402.     int num;
  3403. {
  3404.     if (num == -1)
  3405.     return '"';
  3406.     else if (num < 10)
  3407.     return num + '0';
  3408.     else if (num == DELETION_REGISTER)
  3409.     return '-';
  3410. #ifdef FEAT_CLIPBOARD
  3411.     else if (num == STAR_REGISTER)
  3412.     return '*';
  3413.     else if (num == PLUS_REGISTER)
  3414.     return '+';
  3415. #endif
  3416.     else
  3417.     {
  3418. #ifdef EBCDIC
  3419.     int i;
  3420.  
  3421.     /* EBCDIC is really braindead ... */
  3422.     i = 'a' + (num - 10);
  3423.     if (i > 'i')
  3424.         i += 7;
  3425.     if (i > 'r')
  3426.         i += 8;
  3427.     return i;
  3428. #else
  3429.     return num + 'a' - 10;
  3430. #endif
  3431.     }
  3432. }
  3433.  
  3434. /*
  3435.  * ":dis" and ":registers": Display the contents of the yank registers.
  3436.  */
  3437.     void
  3438. ex_display(eap)
  3439.     exarg_T    *eap;
  3440. {
  3441.     int            i, n;
  3442.     long        j;
  3443.     char_u        *p;
  3444.     struct yankreg    *yb;
  3445.     char_u        name;
  3446.     int            attr;
  3447.     char_u        *arg = eap->arg;
  3448.  
  3449.     if (arg != NULL && *arg == NUL)
  3450.     arg = NULL;
  3451.     attr = hl_attr(HLF_8);
  3452.  
  3453.     /* Highlight title */
  3454.     MSG_PUTS_TITLE(_("\n--- Registers ---"));
  3455.     for (i = -1; i < NUM_REGISTERS; ++i)
  3456.     {
  3457.     if (i == -1)
  3458.     {
  3459.         if (y_previous != NULL)
  3460.         yb = y_previous;
  3461.         else
  3462.         yb = &(y_regs[0]);
  3463.     }
  3464.     else
  3465.         yb = &(y_regs[i]);
  3466.     name = get_register_name(i);
  3467.     if (yb->y_array != NULL
  3468.         && (arg == NULL || vim_strchr(arg, name) != NULL))
  3469.     {
  3470.         msg_putchar('\n');
  3471.         msg_putchar('"');
  3472.         msg_putchar(name);
  3473.         MSG_PUTS("   ");
  3474.  
  3475.         n = (int)Columns - 6;
  3476.         for (j = 0; j < yb->y_size && n > 1; ++j)
  3477.         {
  3478.         if (j)
  3479.         {
  3480.             MSG_PUTS_ATTR("^J", attr);
  3481.             n -= 2;
  3482.         }
  3483.         for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; ++p)
  3484.         {
  3485.             msg_outtrans_len(p, 1);
  3486. #ifdef FEAT_MBYTE
  3487.             if (has_mbyte)
  3488.             p += (*mb_ptr2len_check)(p) - 1;
  3489. #endif
  3490.         }
  3491.         }
  3492.         if (n > 1 && yb->y_type == MLINE)
  3493.         MSG_PUTS_ATTR("^J", attr);
  3494.         out_flush();            /* show one line at a time */
  3495.     }
  3496.     }
  3497.  
  3498.     /*
  3499.      * display last inserted text
  3500.      */
  3501.     if ((p = get_last_insert()) != NULL
  3502.         && (arg == NULL || vim_strchr(arg, '.') != NULL))
  3503.     {
  3504.     MSG_PUTS("\n\".   ");
  3505.     dis_msg(p, TRUE);
  3506.     }
  3507.  
  3508.     /*
  3509.      * display last command line
  3510.      */
  3511.     if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL))
  3512.     {
  3513.     MSG_PUTS("\n\":   ");
  3514.     dis_msg(last_cmdline, FALSE);
  3515.     }
  3516.  
  3517.     /*
  3518.      * display current file name
  3519.      */
  3520.     if (curbuf->b_fname != NULL
  3521.         && (arg == NULL || vim_strchr(arg, '%') != NULL))
  3522.     {
  3523.     MSG_PUTS("\n\"%   ");
  3524.     dis_msg(curbuf->b_fname, FALSE);
  3525.     }
  3526.  
  3527.     /*
  3528.      * display alternate file name
  3529.      */
  3530.     if (arg == NULL || vim_strchr(arg, '%') != NULL)
  3531.     {
  3532.     char_u        *fname;
  3533.     linenr_T    dummy;
  3534.  
  3535.     if (buflist_name_nr(0, &fname, &dummy) != FAIL)
  3536.     {
  3537.         MSG_PUTS("\n\"#   ");
  3538.         dis_msg(fname, FALSE);
  3539.     }
  3540.     }
  3541.  
  3542.     /*
  3543.      * display last search pattern
  3544.      */
  3545.     if (last_search_pat() != NULL
  3546.                  && (arg == NULL || vim_strchr(arg, '/') != NULL))
  3547.     {
  3548.     MSG_PUTS("\n\"/   ");
  3549.     dis_msg(last_search_pat(), FALSE);
  3550.     }
  3551.  
  3552. #ifdef FEAT_EVAL
  3553.     /*
  3554.      * display last used expression
  3555.      */
  3556.     if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL))
  3557.     {
  3558.     MSG_PUTS("\n\"=   ");
  3559.     dis_msg(expr_line, FALSE);
  3560.     }
  3561. #endif
  3562. }
  3563.  
  3564. /*
  3565.  * display a string for do_dis()
  3566.  * truncate at end of screen line
  3567.  */
  3568.     void
  3569. dis_msg(p, skip_esc)
  3570.     char_u    *p;
  3571.     int        skip_esc;        /* if TRUE, ignore trailing ESC */
  3572. {
  3573.     int        n;
  3574. #ifdef FEAT_MBYTE
  3575.     int        l;
  3576. #endif
  3577.  
  3578.     n = (int)Columns - 6;
  3579.     while (*p != NUL
  3580.         && !(*p == ESC && skip_esc && *(p + 1) == NUL)
  3581.         && (n -= ptr2cells(p)) >= 0)
  3582.     {
  3583. #ifdef FEAT_MBYTE
  3584.     if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  3585.     {
  3586.         msg_outtrans_len(p, l);
  3587.         p += l;
  3588.     }
  3589.     else
  3590. #endif
  3591.         msg_outtrans_len(p++, 1);
  3592.     }
  3593. }
  3594.  
  3595. /*
  3596.  * join 'count' lines (minimal 2), including u_save()
  3597.  */
  3598.     void
  3599. do_do_join(count, insert_space)
  3600.     long    count;
  3601.     int        insert_space;
  3602. {
  3603.     if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
  3604.             (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
  3605.     return;
  3606.  
  3607.     while (--count > 0)
  3608.     {
  3609.     line_breakcheck();
  3610.     if (got_int || do_join(insert_space) == FAIL)
  3611.     {
  3612.         beep_flush();
  3613.         break;
  3614.     }
  3615.     }
  3616.  
  3617. #if 0
  3618.     /*
  3619.      * Need to update the screen if the line where the cursor is became too
  3620.      * long to fit on the screen.
  3621.      */
  3622.     update_topline_redraw();
  3623. #endif
  3624. }
  3625.  
  3626. /*
  3627.  * Join two lines at the cursor position.
  3628.  * "redraw" is TRUE when the screen should be updated.
  3629.  * Caller must have setup for undo.
  3630.  *
  3631.  * return FAIL for failure, OK ohterwise
  3632.  */
  3633.     int
  3634. do_join(insert_space)
  3635.     int        insert_space;
  3636. {
  3637.     char_u    *curr;
  3638.     char_u    *next;
  3639.     char_u    *newp;
  3640.     int        endcurr1, endcurr2;
  3641.     int        currsize;    /* size of the current line */
  3642.     int        nextsize;    /* size of the next line */
  3643.     int        spaces;        /* number of spaces to insert */
  3644.     linenr_T    t;
  3645.  
  3646.     if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
  3647.     return FAIL;        /* can't join on last line */
  3648.  
  3649.     curr = ml_get_curline();
  3650.     currsize = (int)STRLEN(curr);
  3651.     endcurr1 = endcurr2 = NUL;
  3652.     if (currsize > 0)
  3653.     {
  3654.     endcurr1 = *(curr + currsize - 1);
  3655.     if (currsize > 1)
  3656.         endcurr2 = *(curr + currsize - 2);
  3657.     }
  3658.  
  3659.     next = ml_get((linenr_T)(curwin->w_cursor.lnum + 1));
  3660.     spaces = 0;
  3661.     if (insert_space)
  3662.     {
  3663.     next = skipwhite(next);
  3664.     if (*next != ')' && currsize != 0 && endcurr1 != TAB)
  3665.     {
  3666.         /* don't add a space if the line is inding in a space */
  3667.         if (endcurr1 == ' ')
  3668.         endcurr1 = endcurr2;
  3669.         else
  3670.         ++spaces;
  3671.         /* extra space when 'joinspaces' set and line ends in '.' */
  3672.         if (       p_js
  3673.             && (endcurr1 == '.'
  3674.             || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
  3675.                 && (endcurr1 == '?' || endcurr1 == '!'))))
  3676.         ++spaces;
  3677.     }
  3678.     }
  3679.     nextsize = (int)STRLEN(next);
  3680.  
  3681.     newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
  3682.     if (newp == NULL)
  3683.     return FAIL;
  3684.  
  3685.     /*
  3686.      * Insert the next line first, because we already have that pointer.
  3687.      * Curr has to be obtained again, because getting next will have
  3688.      * invalidated it.
  3689.      */
  3690.     mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
  3691.  
  3692.     curr = ml_get_curline();
  3693.     mch_memmove(newp, curr, (size_t)currsize);
  3694.  
  3695.     copy_spaces(newp + currsize, (size_t)spaces);
  3696.  
  3697.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  3698.  
  3699.     /* Only report the change in the first line here, del_lines() will report
  3700.      * the deleted line. */
  3701.     changed_lines(curwin->w_cursor.lnum, currsize,
  3702.                            curwin->w_cursor.lnum + 1, 0L);
  3703.  
  3704.     /*
  3705.      * Delete the following line. To do this we move the cursor there
  3706.      * briefly, and then move it back. After del_lines() the cursor may
  3707.      * have moved up (last line deleted), so the current lnum is kept in t.
  3708.      */
  3709.     t = curwin->w_cursor.lnum;
  3710.     ++curwin->w_cursor.lnum;
  3711.     del_lines(1L, FALSE);
  3712.     curwin->w_cursor.lnum = t;
  3713.  
  3714.     /*
  3715.      * go to first character of the joined line
  3716.      */
  3717.     curwin->w_cursor.col = currsize;
  3718.     check_cursor_col();
  3719. #ifdef FEAT_VIRTUALEDIT
  3720.     curwin->w_cursor.coladd = 0;
  3721. #endif
  3722.     curwin->w_set_curswant = TRUE;
  3723.  
  3724.     return OK;
  3725. }
  3726.  
  3727. #ifdef FEAT_COMMENTS
  3728. /*
  3729.  * Return TRUE if the two comment leaders given are the same.  The cursor is
  3730.  * in the first line.  White-space is ignored.    Note that the whole of
  3731.  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
  3732.  */
  3733.     static int
  3734. same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
  3735.     int        leader1_len;
  3736.     char_u  *leader1_flags;
  3737.     int        leader2_len;
  3738.     char_u  *leader2_flags;
  3739. {
  3740.     int        idx1 = 0, idx2 = 0;
  3741.     char_u  *p;
  3742.     char_u  *line1;
  3743.     char_u  *line2;
  3744.  
  3745.     if (leader1_len == 0)
  3746.     return (leader2_len == 0);
  3747.  
  3748.     /*
  3749.      * If first leader has 'f' flag, the lines can be joined only if the
  3750.      * second line does not have a leader.
  3751.      * If first leader has 'e' flag, the lines can never be joined.
  3752.      * If fist leader has 's' flag, the lines can only be joined if there is
  3753.      * some text after it and the second line has the 'm' flag.
  3754.      */
  3755.     if (leader1_flags != NULL)
  3756.     {
  3757.     for (p = leader1_flags; *p && *p != ':'; ++p)
  3758.     {
  3759.         if (*p == COM_FIRST)
  3760.         return (leader2_len == 0);
  3761.         if (*p == COM_END)
  3762.         return FALSE;
  3763.         if (*p == COM_START)
  3764.         {
  3765.         if (*(ml_get_curline() + leader1_len) == NUL)
  3766.             return FALSE;
  3767.         if (leader2_flags == NULL || leader2_len == 0)
  3768.             return FALSE;
  3769.         for (p = leader2_flags; *p && *p != ':'; ++p)
  3770.             if (*p == COM_MIDDLE)
  3771.             return TRUE;
  3772.         return FALSE;
  3773.         }
  3774.     }
  3775.     }
  3776.  
  3777.     /*
  3778.      * Get current line and next line, compare the leaders.
  3779.      * The first line has to be saved, only one line can be locked at a time.
  3780.      */
  3781.     line1 = vim_strsave(ml_get_curline());
  3782.     if (line1 != NULL)
  3783.     {
  3784.     for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
  3785.         ;
  3786.     line2 = ml_get(curwin->w_cursor.lnum + 1);
  3787.     for (idx2 = 0; idx2 < leader2_len; ++idx2)
  3788.     {
  3789.         if (!vim_iswhite(line2[idx2]))
  3790.         {
  3791.         if (line1[idx1++] != line2[idx2])
  3792.             break;
  3793.         }
  3794.         else
  3795.         while (vim_iswhite(line1[idx1]))
  3796.             ++idx1;
  3797.     }
  3798.     vim_free(line1);
  3799.     }
  3800.     return (idx2 == leader2_len && idx1 == leader1_len);
  3801. }
  3802. #endif
  3803.  
  3804. /*
  3805.  * implementation of the format operator 'gq'
  3806.  */
  3807.     void
  3808. op_format(oap)
  3809.     oparg_T    *oap;
  3810. {
  3811.     long    old_line_count = curbuf->b_ml.ml_line_count;
  3812.     int        is_not_par;        /* current line not part of parag. */
  3813.     int        next_is_not_par;    /* next line not part of paragraph */
  3814.     int        is_end_par;        /* at end of paragraph */
  3815.     int        prev_is_end_par = FALSE;/* prev. line not part of parag. */
  3816.     int        next_is_start_par = FALSE;
  3817. #ifdef FEAT_COMMENTS
  3818.     int        leader_len = 0;        /* leader len of current line */
  3819.     int        next_leader_len;    /* leader len of next line */
  3820.     char_u    *leader_flags = NULL;    /* flags for leader of current line */
  3821.     char_u    *next_leader_flags;    /* flags for leader of next line */
  3822.     int        do_comments;        /* format comments */
  3823. #endif
  3824.     int        advance = TRUE;
  3825.     int        second_indent = -1;
  3826.     int        do_second_indent;
  3827.     int        do_number_indent;
  3828.     int        first_par_line = TRUE;
  3829.     int        smd_save;
  3830.     long    count;
  3831.     int        need_set_indent = TRUE;    /* set indent of next paragraph */
  3832.     int        force_format = FALSE;
  3833.     int        max_len;
  3834.  
  3835.     if (u_save((linenr_T)(oap->start.lnum - 1),
  3836.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  3837.     return;
  3838.  
  3839. #ifdef FEAT_VISUAL
  3840.     if (oap->is_VIsual)
  3841.     /* When there is no change: need to remove the Visual selection */
  3842.     redraw_curbuf_later(INVERTED);
  3843. #endif
  3844.  
  3845.     /* length of a line to force formatting: 3 * 'tw' */
  3846.     max_len = comp_textwidth(TRUE) * 3;
  3847.  
  3848.     /* Set '[ mark at the start of the formatted area */
  3849.     curbuf->b_op_start = oap->start;
  3850.  
  3851.     /* check for 'q', '2' and '1' in 'formatoptions' */
  3852. #ifdef FEAT_COMMENTS
  3853.     do_comments = has_format_option(FO_Q_COMS);
  3854. #endif
  3855.     do_second_indent = has_format_option(FO_Q_SECOND);
  3856.     do_number_indent = has_format_option(FO_Q_NUMBER);
  3857.  
  3858.     /*
  3859.      * Get info about the previous and current line.
  3860.      */
  3861.     if (curwin->w_cursor.lnum > 1)
  3862.     is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
  3863. #ifdef FEAT_COMMENTS
  3864.                 , &leader_len, &leader_flags, do_comments
  3865. #endif
  3866.                 );
  3867.     else
  3868.     is_not_par = TRUE;
  3869.     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
  3870. #ifdef FEAT_COMMENTS
  3871.                , &next_leader_len, &next_leader_flags, do_comments
  3872. #endif
  3873.                 );
  3874.     is_end_par = (is_not_par || next_is_not_par);
  3875.  
  3876.     curwin->w_cursor.lnum--;
  3877.     for (count = oap->line_count; count > 0 && !got_int; --count)
  3878.     {
  3879.     /*
  3880.      * Advance to next paragraph.
  3881.      */
  3882.     if (advance)
  3883.     {
  3884.         curwin->w_cursor.lnum++;
  3885.         prev_is_end_par = is_end_par;
  3886.         is_not_par = next_is_not_par;
  3887. #ifdef FEAT_COMMENTS
  3888.         leader_len = next_leader_len;
  3889.         leader_flags = next_leader_flags;
  3890. #endif
  3891.     }
  3892.  
  3893.     /*
  3894.      * The last line to be formatted.
  3895.      */
  3896.     if (count == 1)
  3897.     {
  3898.         next_is_not_par = TRUE;
  3899. #ifdef FEAT_COMMENTS
  3900.         next_leader_len = 0;
  3901.         next_leader_flags = NULL;
  3902. #endif
  3903.     }
  3904.     else
  3905.     {
  3906.         next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
  3907. #ifdef FEAT_COMMENTS
  3908.                , &next_leader_len, &next_leader_flags, do_comments
  3909. #endif
  3910.                     );
  3911.         if (do_number_indent)
  3912.         next_is_start_par =
  3913.                (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
  3914.     }
  3915.     advance = TRUE;
  3916.     is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
  3917.  
  3918.     /*
  3919.      * Skip lines that are not in a paragraph.
  3920.      */
  3921.     if (!is_not_par)
  3922.     {
  3923.         /*
  3924.          * For the first line of a paragraph, check indent of second line.
  3925.          * Don't do this for comments and empty lines.
  3926.          */
  3927.         if (first_par_line
  3928.             && (do_second_indent || do_number_indent)
  3929.             && prev_is_end_par
  3930.             && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  3931. #ifdef FEAT_COMMENTS
  3932.             && leader_len == 0
  3933.             && next_leader_len == 0
  3934. #endif
  3935.             )
  3936.         {
  3937.         if (do_second_indent
  3938.             && !lineempty(curwin->w_cursor.lnum + 1))
  3939.             second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
  3940.         else if (do_number_indent)
  3941.             second_indent = get_number_indent(curwin->w_cursor.lnum);
  3942.         }
  3943.  
  3944.         /*
  3945.          * When the comment leader changes, it's the end of the paragraph.
  3946.          */
  3947.         if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
  3948. #ifdef FEAT_COMMENTS
  3949.             || !same_leader(leader_len, leader_flags,
  3950.                       next_leader_len, next_leader_flags)
  3951. #endif
  3952.             )
  3953.         is_end_par = TRUE;
  3954.  
  3955.         /*
  3956.          * If we have got to the end of a paragraph, or the line is
  3957.          * getting long, format it.
  3958.          */
  3959.         if (is_end_par || force_format)
  3960.         {
  3961.         if (need_set_indent)
  3962.             /* replace indent in first line with minimal number of
  3963.              * tabs and spaces, according to current options */
  3964.             (void)set_indent(get_indent(), SIN_CHANGED);
  3965.  
  3966.         /* put cursor on last non-space */
  3967.         coladvance((colnr_T)MAXCOL);
  3968.         while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
  3969.             dec_cursor();
  3970.  
  3971.         /* do the formatting, without 'showmode' */
  3972.         State = INSERT;    /* for open_line() */
  3973.         smd_save = p_smd;
  3974.         p_smd = FALSE;
  3975.         insertchar(NUL, INSCHAR_FORMAT
  3976. #ifdef FEAT_COMMENTS
  3977.             + (do_comments ? INSCHAR_DO_COM : 0)
  3978. #endif
  3979.             , second_indent);
  3980.         State = NORMAL;
  3981.         p_smd = smd_save;
  3982.         second_indent = -1;
  3983.         /* at end of par.: need to set indent of next par. */
  3984.         need_set_indent = is_end_par;
  3985.         if (is_end_par)
  3986.             first_par_line = TRUE;
  3987.         force_format = FALSE;
  3988.         }
  3989.  
  3990.         /*
  3991.          * When still in same paragraph, join the lines together.  But
  3992.          * first delete the comment leader from the second line.
  3993.          */
  3994.         if (!is_end_par)
  3995.         {
  3996.         advance = FALSE;
  3997.         curwin->w_cursor.lnum++;
  3998.         curwin->w_cursor.col = 0;
  3999. #ifdef FEAT_COMMENTS
  4000.         (void)del_bytes((long)next_leader_len, FALSE);
  4001. #endif
  4002.         curwin->w_cursor.lnum--;
  4003.         if (do_join(TRUE) == FAIL)
  4004.         {
  4005.             beep_flush();
  4006.             break;
  4007.         }
  4008.         first_par_line = FALSE;
  4009.         /* If the line is getting long, format it next time */
  4010.         if (STRLEN(ml_get_curline()) > (size_t)max_len)
  4011.             force_format = TRUE;
  4012.         else
  4013.             force_format = FALSE;
  4014.         }
  4015.     }
  4016.     line_breakcheck();
  4017.     }
  4018.  
  4019.     /*
  4020.      * Leave the cursor at the first non-blank of the last formatted line.
  4021.      * If the cursor was moved one line back (e.g. with "Q}") go to the next
  4022.      * line, so "." will do the next lines.
  4023.      */
  4024.     if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  4025.     ++curwin->w_cursor.lnum;
  4026.     beginline(BL_WHITE | BL_FIX);
  4027.     msgmore(curbuf->b_ml.ml_line_count - old_line_count);
  4028.  
  4029.     /* put '] mark on the end of the formatted area */
  4030.     curbuf->b_op_end = curwin->w_cursor;
  4031. }
  4032.  
  4033. /*
  4034.  * Blank lines, and lines containing only the comment leader, are left
  4035.  * untouched by the formatting.  The function returns TRUE in this
  4036.  * case.  It also returns TRUE when a line starts with the end of a comment
  4037.  * ('e' in comment flags), so that this line is skipped, and not joined to the
  4038.  * previous line.  A new paragraph starts after a blank line, or when the
  4039.  * comment leader changes -- webb.
  4040.  */
  4041. #ifdef FEAT_COMMENTS
  4042.     static int
  4043. fmt_check_par(lnum, leader_len, leader_flags, do_comments)
  4044.     linenr_T    lnum;
  4045.     int        *leader_len;
  4046.     char_u    **leader_flags;
  4047.     int        do_comments;
  4048. {
  4049.     char_u    *flags = NULL;        /* init for GCC */
  4050.     char_u    *ptr;
  4051.  
  4052.     ptr = ml_get(lnum);
  4053.     if (do_comments)
  4054.     *leader_len = get_leader_len(ptr, leader_flags, FALSE);
  4055.     else
  4056.     *leader_len = 0;
  4057.  
  4058.     if (*leader_len > 0)
  4059.     {
  4060.     /*
  4061.      * Search for 'e' flag in comment leader flags.
  4062.      */
  4063.     flags = *leader_flags;
  4064.     while (*flags && *flags != ':' && *flags != COM_END)
  4065.         ++flags;
  4066.     }
  4067.  
  4068.     return (*skipwhite(ptr + *leader_len) == NUL
  4069.         || (*leader_len > 0 && *flags == COM_END)
  4070.         || startPS(lnum, NUL, FALSE));
  4071. }
  4072. #else
  4073.     static int
  4074. fmt_check_par(lnum)
  4075.     linenr_T    lnum;
  4076. {
  4077.     return (*skipwhite(ml_get(lnum)) == NUL || startPS(lnum, NUL, FALSE));
  4078. }
  4079. #endif
  4080.  
  4081. /*
  4082.  * prepare a few things for block mode yank/delete/tilde
  4083.  *
  4084.  * for delete:
  4085.  * - textlen includes the first/last char to be (partly) deleted
  4086.  * - start/endspaces is the number of columns that are taken by the
  4087.  *   first/last deleted char minus the number of columns that have to be
  4088.  *   deleted.  for yank and tilde:
  4089.  * - textlen includes the first/last char to be wholly yanked
  4090.  * - start/endspaces is the number of columns of the first/last yanked char
  4091.  *   that are to be yanked.
  4092.  */
  4093.     static void
  4094. block_prep(oap, bdp, lnum, is_del)
  4095.     oparg_T        *oap;
  4096.     struct block_def    *bdp;
  4097.     linenr_T        lnum;
  4098.     int            is_del;
  4099. {
  4100.     int        incr = 0;
  4101.     char_u    *pend;
  4102.     char_u    *pstart;
  4103.     char_u    *line;
  4104.     char_u    *prev_pstart;
  4105.     char_u    *prev_pend;
  4106.  
  4107.     bdp->startspaces = 0;
  4108.     bdp->endspaces = 0;
  4109.     bdp->textlen = 0;
  4110.     bdp->start_vcol = 0;
  4111.     bdp->end_vcol = 0;
  4112. #ifdef FEAT_VISUALEXTRA
  4113.     bdp->is_short = FALSE;
  4114.     bdp->is_oneChar = FALSE;
  4115.     bdp->pre_whitesp = 0;
  4116.     bdp->pre_whitesp_c = 0;
  4117.     bdp->end_char_vcols = 0;
  4118. #endif
  4119.     bdp->start_char_vcols = 0;
  4120.  
  4121.     line = ml_get(lnum);
  4122.     pstart = line;
  4123.     prev_pstart = line;
  4124.     while (bdp->start_vcol < oap->start_vcol && *pstart)
  4125.     {
  4126.     /* Count a tab for what it's worth (if list mode not on) */
  4127.     incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol);
  4128.     bdp->start_vcol += incr;
  4129. #ifdef FEAT_VISUALEXTRA
  4130.     if (vim_iswhite(*pstart))
  4131.     {
  4132.         bdp->pre_whitesp += incr;
  4133.         bdp->pre_whitesp_c++;
  4134.     }
  4135.     else
  4136.     {
  4137.         bdp->pre_whitesp = 0;
  4138.         bdp->pre_whitesp_c = 0;
  4139.     }
  4140. #endif
  4141.     prev_pstart = pstart;
  4142. #ifdef FEAT_MBYTE
  4143.     if (has_mbyte)
  4144.         pstart += (*mb_ptr2len_check)(pstart);
  4145.     else
  4146. #endif
  4147.         ++pstart;
  4148.     }
  4149.     bdp->start_char_vcols = incr;
  4150.     if (bdp->start_vcol < oap->start_vcol)    /* line too short */
  4151.     {
  4152.     bdp->end_vcol = bdp->start_vcol;
  4153. #ifdef FEAT_VISUALEXTRA
  4154.     bdp->is_short = TRUE;
  4155. #endif
  4156.     if (!is_del || oap->op_type == OP_APPEND)
  4157.         bdp->endspaces = oap->end_vcol - oap->start_vcol + 1;
  4158.     }
  4159.     else
  4160.     {
  4161.     /* notice: this converts partly selected Multibyte characters to
  4162.      * spaces, too. */
  4163.     bdp->startspaces = bdp->start_vcol - oap->start_vcol;
  4164.     if (is_del && bdp->startspaces)
  4165.         bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
  4166.     pend = pstart;
  4167.     bdp->end_vcol = bdp->start_vcol;
  4168.     if (bdp->end_vcol > oap->end_vcol)    /* it's all in one character */
  4169.     {
  4170. #ifdef FEAT_VISUALEXTRA
  4171.         bdp->is_oneChar = TRUE;
  4172. #endif
  4173.         if (oap->op_type == OP_INSERT)
  4174.         bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
  4175.         else if (oap->op_type == OP_APPEND)
  4176.         {
  4177.         bdp->startspaces += oap->end_vcol - oap->start_vcol + 1;
  4178.         bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
  4179.         }
  4180.         else
  4181.         {
  4182.         bdp->startspaces = oap->end_vcol - oap->start_vcol + 1;
  4183.         if (is_del && oap->op_type != OP_LSHIFT)
  4184.         {
  4185.             /* just putting the sum of those two into
  4186.              * bdp->startspaces doesn't work for Visual replace,
  4187.              * so we have to split the tab in two */
  4188.             bdp->startspaces = bdp->start_char_vcols
  4189.                     - (bdp->start_vcol - oap->start_vcol);
  4190.             bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
  4191.         }
  4192.         }
  4193.     }
  4194.     else
  4195.     {
  4196.         prev_pend = pend;
  4197.         while (bdp->end_vcol <= oap->end_vcol && *pend != NUL)
  4198.         {
  4199.         /* Count a tab for what it's worth (if list mode not on) */
  4200.         prev_pend = pend;
  4201.         incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol);
  4202.         bdp->end_vcol += incr;
  4203.         }
  4204.         if (bdp->end_vcol <= oap->end_vcol
  4205.             && (!is_del
  4206.             || oap->op_type == OP_APPEND
  4207.             || oap->op_type == OP_REPLACE)) /* line too short */
  4208.         {
  4209. #ifdef FEAT_VISUALEXTRA
  4210.         bdp->is_short = TRUE;
  4211. #endif
  4212.         /* Alternative: include spaces to fill up the block.
  4213.          * Disadvantage: can lead to trailing spaces when the line is
  4214.          * short where the text is put */
  4215.         /* if (!is_del || oap->op_type == OP_APPEND) */
  4216.         if (oap->op_type == OP_APPEND || virtual_active())
  4217.             bdp->endspaces = oap->end_vcol - bdp->end_vcol
  4218.                     + oap->inclusive;
  4219.         else
  4220.             bdp->endspaces = 0; /* replace doesn't add characters */
  4221.         }
  4222.         else if (bdp->end_vcol > oap->end_vcol)
  4223.         {
  4224.         bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
  4225.         if (!is_del && bdp->endspaces)
  4226.         {
  4227.             bdp->endspaces = incr - bdp->endspaces;
  4228.             if (pend != pstart)
  4229.             pend = prev_pend;
  4230.         }
  4231.         }
  4232.     }
  4233. #ifdef FEAT_VISUALEXTRA
  4234.     bdp->end_char_vcols = incr;
  4235. #endif
  4236.     if (is_del && bdp->startspaces)
  4237.         pstart = prev_pstart;
  4238.     bdp->textlen = (int)(pend - pstart);
  4239.     }
  4240.     bdp->textcol = (colnr_T) (pstart - line);
  4241.     bdp->textstart = pstart;
  4242. }
  4243.  
  4244. #ifdef FEAT_RIGHTLEFT
  4245. static void reverse_line __ARGS((char_u *s));
  4246.  
  4247.     static void
  4248. reverse_line(s)
  4249.     char_u *s;
  4250. {
  4251.     int        i, j;
  4252.     char_u  c;
  4253.  
  4254.     if ((i = (int)STRLEN(s) - 1) <= 0)
  4255.     return;
  4256.  
  4257.     curwin->w_cursor.col = i - curwin->w_cursor.col;
  4258.     for (j = 0; j < i; j++, i--)
  4259.     {
  4260.     c = s[i]; s[i] = s[j]; s[j] = c;
  4261.     }
  4262. }
  4263.  
  4264. # define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr);
  4265. #else
  4266. # define RLADDSUBFIX(ptr)
  4267. #endif
  4268.  
  4269. /*
  4270.  * add or subtract 'Prenum1' from a number in a line
  4271.  * 'command' is CTRL-A for add, CTRL-X for subtract
  4272.  *
  4273.  * return FAIL for failure, OK otherwise
  4274.  */
  4275.     int
  4276. do_addsub(command, Prenum1)
  4277.     int        command;
  4278.     linenr_T    Prenum1;
  4279. {
  4280.     int        col;
  4281.     char_u    *buf1;
  4282.     char_u    buf2[NUMBUFLEN];
  4283.     int        hex;        /* 'X' or 'x': hex; '0': octal */
  4284.     static int    hexupper = FALSE;    /* 0xABC */
  4285.     long_u    n;
  4286.     long_u    oldn;
  4287.     char_u    *ptr;
  4288.     int        c;
  4289.     int        length = 0;        /* character length of the number */
  4290.     int        todel;
  4291.     int        dohex;
  4292.     int        dooct;
  4293.     int        doalp;
  4294.     int        firstdigit;
  4295.     int        negative;
  4296.     int        subtract;
  4297.  
  4298.     dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL);    /* "heX" */
  4299.     dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL);    /* "Octal" */
  4300.     doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL);    /* "alPha" */
  4301.  
  4302.     ptr = ml_get_curline();
  4303.     RLADDSUBFIX(ptr);
  4304.  
  4305.     /*
  4306.      * First check if we are on a hexadecimal number, after the "0x".
  4307.      */
  4308.     col = curwin->w_cursor.col;
  4309.     if (dohex)
  4310.     while (col > 0 && isxdigit(ptr[col]))
  4311.         --col;
  4312.     if (       dohex
  4313.         && col > 0
  4314.         && (ptr[col] == 'X'
  4315.         || ptr[col] == 'x')
  4316.         && ptr[col - 1] == '0'
  4317.         && isxdigit(ptr[col + 1]))
  4318.     {
  4319.     /*
  4320.      * Found hexadecimal number, move to its start.
  4321.      */
  4322.     --col;
  4323.     }
  4324.     else
  4325.     {
  4326.     /*
  4327.      * Search forward and then backward to find the start of number.
  4328.      */
  4329.     col = curwin->w_cursor.col;
  4330.  
  4331.     while (ptr[col] != NUL
  4332.         && !isdigit(ptr[col])
  4333.         && !(doalp && ASCII_ISALPHA(ptr[col])))
  4334.         ++col;
  4335.  
  4336.     while (col > 0
  4337.         && isdigit(ptr[col - 1])
  4338.         && !(doalp && ASCII_ISALPHA(ptr[col])))
  4339.         --col;
  4340.     }
  4341.  
  4342.     /* truncate to max length of a number */
  4343.     if (length >= NUMBUFLEN - 1)
  4344.     length = NUMBUFLEN - 2;
  4345.  
  4346.     /*
  4347.      * If a number was found, and saving for undo works, replace the number.
  4348.      */
  4349.     firstdigit = ptr[col];
  4350.     RLADDSUBFIX(ptr);
  4351.     if ((!isdigit(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
  4352.         || u_save_cursor() != OK)
  4353.     {
  4354.     beep_flush();
  4355.     return FAIL;
  4356.     }
  4357.  
  4358.     /* get ptr again, because u_save() may have changed it */
  4359.     ptr = ml_get_curline();
  4360.     RLADDSUBFIX(ptr);
  4361.  
  4362.     if (doalp && ASCII_ISALPHA(firstdigit))
  4363.     {
  4364.     /* decrement or increment alphabetic character */
  4365.     if (command == Ctrl_X)
  4366.     {
  4367.         if (CharOrd(firstdigit) < Prenum1)
  4368.         {
  4369.         if (isupper(firstdigit))
  4370.             firstdigit = 'A';
  4371.         else
  4372.             firstdigit = 'a';
  4373.         }
  4374.         else
  4375. #ifdef EBCDIC
  4376.         firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
  4377. #else
  4378.         firstdigit -= Prenum1;
  4379. #endif
  4380.     }
  4381.     else
  4382.     {
  4383.         if (26 - CharOrd(firstdigit) - 1 < Prenum1)
  4384.         {
  4385.         if (isupper(firstdigit))
  4386.             firstdigit = 'Z';
  4387.         else
  4388.             firstdigit = 'z';
  4389.         }
  4390.         else
  4391. #ifdef EBCDIC
  4392.         firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
  4393. #else
  4394.         firstdigit += Prenum1;
  4395. #endif
  4396.     }
  4397.     curwin->w_cursor.col = col;
  4398.     (void)del_char(FALSE);
  4399.     ins_char(firstdigit);
  4400.     }
  4401.     else
  4402.     {
  4403.     negative = FALSE;
  4404.     if (col > 0 && ptr[col - 1] == '-')        /* negative number */
  4405.     {
  4406.         --col;
  4407.         negative = TRUE;
  4408.     }
  4409.  
  4410.     /* get the number value (unsigned) */
  4411.     vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
  4412.  
  4413.     /* ignore leading '-' for hex and octal numbers */
  4414.     if (hex && negative)
  4415.     {
  4416.         ++col;
  4417.         --length;
  4418.         negative = FALSE;
  4419.     }
  4420.  
  4421.     /* add or subtract */
  4422.     subtract = FALSE;
  4423.     if (command == Ctrl_X)
  4424.         subtract ^= TRUE;
  4425.     if (negative)
  4426.         subtract ^= TRUE;
  4427.  
  4428.     oldn = n;
  4429.     if (subtract)
  4430.         n -= (unsigned long)Prenum1;
  4431.     else
  4432.         n += (unsigned long)Prenum1;
  4433.  
  4434.     /* handle wraparound for decimal numbers */
  4435.     if (!hex)
  4436.     {
  4437.         if (subtract)
  4438.         {
  4439.         if (n > oldn)
  4440.         {
  4441.             n = 1 + (n ^ (unsigned long)-1);
  4442.             negative ^= TRUE;
  4443.         }
  4444.         }
  4445.         else /* add */
  4446.         {
  4447.         if (n < oldn)
  4448.         {
  4449.             n = (n ^ (unsigned long)-1);
  4450.             negative ^= TRUE;
  4451.         }
  4452.         }
  4453.         if (n == 0)
  4454.         negative = FALSE;
  4455.     }
  4456.  
  4457.     /*
  4458.      * Delete the old number.
  4459.      */
  4460.     curwin->w_cursor.col = col;
  4461.     todel = length;
  4462.     c = gchar_cursor();
  4463.     /*
  4464.      * Don't include the '-' in the length, only the length of the part
  4465.      * after it is kept the same.
  4466.      */
  4467.     if (c == '-')
  4468.         --length;
  4469.     while (todel-- > 0)
  4470.     {
  4471.         if (c < 0x100 && isalpha(c))
  4472.         {
  4473.         if (isupper(c))
  4474.             hexupper = TRUE;
  4475.         else
  4476.             hexupper = FALSE;
  4477.         }
  4478.         /* del_char() will mark line needing displaying */
  4479.         (void)del_char(FALSE);
  4480.         c = gchar_cursor();
  4481.     }
  4482.  
  4483.     /*
  4484.      * Prepare the leading characters in buf1[].
  4485.      * When there are many leading zeros it could be very long.  Allocate
  4486.      * a bit too much.
  4487.      */
  4488.     buf1 = alloc((unsigned)length + NUMBUFLEN);
  4489.     if (buf1 == NULL)
  4490.         return FAIL;
  4491.     ptr = buf1;
  4492.     if (negative)
  4493.     {
  4494.         *ptr++ = '-';
  4495.     }
  4496.     if (hex)
  4497.     {
  4498.         *ptr++ = '0';
  4499.         --length;
  4500.     }
  4501.     if (hex == 'x' || hex == 'X')
  4502.     {
  4503.         *ptr++ = hex;
  4504.         --length;
  4505.     }
  4506.  
  4507.     /*
  4508.      * Put the number characters in buf2[].
  4509.      */
  4510.     if (hex == 0)
  4511.         sprintf((char *)buf2, "%lu", n);
  4512.     else if (hex == '0')
  4513.         sprintf((char *)buf2, "%lo", n);
  4514.     else if (hex && hexupper)
  4515.         sprintf((char *)buf2, "%lX", n);
  4516.     else
  4517.         sprintf((char *)buf2, "%lx", n);
  4518.     length -= (int)STRLEN(buf2);
  4519.  
  4520.     /*
  4521.      * adjust number of zeros to the new number of digits, so the
  4522.      * total length of the number remains the same
  4523.      */
  4524.     if (firstdigit == '0')
  4525.         while (length-- > 0)
  4526.         *ptr++ = '0';
  4527.     *ptr = NUL;
  4528.     STRCAT(buf1, buf2);
  4529.     ins_str(buf1);        /* insert the new number */
  4530.     vim_free(buf1);
  4531.     }
  4532.     --curwin->w_cursor.col;
  4533.     curwin->w_set_curswant = TRUE;
  4534. #ifdef FEAT_RIGHTLEFT
  4535.     ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
  4536.     RLADDSUBFIX(ptr);
  4537. #endif
  4538.     return OK;
  4539. }
  4540.  
  4541. #ifdef FEAT_VIMINFO
  4542.     int
  4543. read_viminfo_register(virp, force)
  4544.     vir_T    *virp;
  4545.     int        force;
  4546. {
  4547.     int        eof;
  4548.     int        do_it = TRUE;
  4549.     int        size;
  4550.     int        limit;
  4551.     int        i;
  4552.     int        set_prev = FALSE;
  4553.     char_u    *str;
  4554.     char_u    **array = NULL;
  4555.  
  4556.     /* We only get here (hopefully) if line[0] == '"' */
  4557.     str = virp->vir_line + 1;
  4558.     if (*str == '"')
  4559.     {
  4560.     set_prev = TRUE;
  4561.     str++;
  4562.     }
  4563.     if (!ASCII_ISALNUM(*str) && *str != '-')
  4564.     {
  4565.     if (viminfo_error(_("Illegal register name"), virp->vir_line))
  4566.         return TRUE;    /* too many errors, pretend end-of-file */
  4567.     do_it = FALSE;
  4568.     }
  4569.     get_yank_register(*str++, FALSE);
  4570.     if (!force && y_current->y_array != NULL)
  4571.     do_it = FALSE;
  4572.     size = 0;
  4573.     limit = 100;    /* Optimized for registers containing <= 100 lines */
  4574.     if (do_it)
  4575.     {
  4576.     if (set_prev)
  4577.         y_previous = y_current;
  4578.     vim_free(y_current->y_array);
  4579.     array = y_current->y_array =
  4580.                (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
  4581.     str = skipwhite(str);
  4582.     if (STRNCMP(str, "CHAR", 4) == 0)
  4583.         y_current->y_type = MCHAR;
  4584.     else if (STRNCMP(str, "BLOCK", 5) == 0)
  4585.         y_current->y_type = MBLOCK;
  4586.     else
  4587.         y_current->y_type = MLINE;
  4588.     /* get the block width; if it's missing we get a zero, which is OK */
  4589.     str = skipwhite(skiptowhite(str));
  4590.     y_current->y_width = getdigits(&str);
  4591.     }
  4592.  
  4593.     while (!(eof = viminfo_readline(virp))
  4594.             && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
  4595.     {
  4596.     if (do_it)
  4597.     {
  4598.         if (size >= limit)
  4599.         {
  4600.         y_current->y_array = (char_u **)
  4601.                   alloc((unsigned)(limit * 2 * sizeof(char_u *)));
  4602.         for (i = 0; i < limit; i++)
  4603.             y_current->y_array[i] = array[i];
  4604.         vim_free(array);
  4605.         limit *= 2;
  4606.         array = y_current->y_array;
  4607.         }
  4608.         str = viminfo_readstring(virp, 1, TRUE);
  4609.         if (str != NULL)
  4610.         array[size++] = str;
  4611.         else
  4612.         do_it = FALSE;
  4613.     }
  4614.     }
  4615.     if (do_it)
  4616.     {
  4617.     if (size == 0)
  4618.     {
  4619.         vim_free(array);
  4620.         y_current->y_array = NULL;
  4621.     }
  4622.     else if (size < limit)
  4623.     {
  4624.         y_current->y_array =
  4625.             (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
  4626.         for (i = 0; i < size; i++)
  4627.         y_current->y_array[i] = array[i];
  4628.         vim_free(array);
  4629.     }
  4630.     y_current->y_size = size;
  4631.     }
  4632.     return eof;
  4633. }
  4634.  
  4635.     void
  4636. write_viminfo_registers(fp)
  4637.     FILE    *fp;
  4638. {
  4639.     int        i, j;
  4640.     char_u  *type;
  4641.     char_u  c;
  4642.     int        num_lines;
  4643.     int        max_num_lines;
  4644.  
  4645.     fprintf(fp, _("\n# Registers:\n"));
  4646.  
  4647.     max_num_lines = get_viminfo_parameter('"');
  4648.     if (max_num_lines == 0)
  4649.     return;
  4650.     for (i = 0; i < NUM_REGISTERS; i++)
  4651.     {
  4652.     if (y_regs[i].y_array == NULL)
  4653.         continue;
  4654. #ifdef FEAT_CLIPBOARD
  4655.     /* Skip '*'/'+' register, we don't want them back next time */
  4656.     if (i == STAR_REGISTER || i == PLUS_REGISTER)
  4657.         continue;
  4658. #endif
  4659.     switch (y_regs[i].y_type)
  4660.     {
  4661.         case MLINE:
  4662.         type = (char_u *)"LINE";
  4663.         break;
  4664.         case MCHAR:
  4665.         type = (char_u *)"CHAR";
  4666.         break;
  4667.         case MBLOCK:
  4668.         type = (char_u *)"BLOCK";
  4669.         break;
  4670.         default:
  4671.         sprintf((char *)IObuff, _("Unknown register type %d"),
  4672.             y_regs[i].y_type);
  4673.         emsg(IObuff);
  4674.         type = (char_u *)"LINE";
  4675.         break;
  4676.     }
  4677.     if (y_previous == &y_regs[i])
  4678.         fprintf(fp, "\"");
  4679.     c = get_register_name(i);
  4680.     fprintf(fp, "\"%c\t%s\t%d\n", c, type, y_regs[i].y_width);
  4681.     num_lines = y_regs[i].y_size;
  4682.  
  4683.     /* If max_num_lines < 0, then we save ALL the lines in the register */
  4684.     if (max_num_lines > 0 && num_lines > max_num_lines)
  4685.         num_lines = max_num_lines;
  4686.     for (j = 0; j < num_lines; j++)
  4687.     {
  4688.         putc('\t', fp);
  4689.         viminfo_writestring(fp, y_regs[i].y_array[j]);
  4690.     }
  4691.     }
  4692. }
  4693. #endif /* FEAT_VIMINFO */
  4694.  
  4695. #if defined(FEAT_CLIPBOARD) || defined(PROTO)
  4696. /*
  4697.  * SELECTION / PRIMARY ('*')
  4698.  *
  4699.  * Text selection stuff that uses the GUI selection register '*'.  When using a
  4700.  * GUI this may be text from another window, otherwise it is the last text we
  4701.  * had highlighted with VIsual mode.  With mouse support, clicking the middle
  4702.  * button performs the paste, otherwise you will need to do <"*p>. "
  4703.  * If not under X, it is synonymous with the clipboard register '+'.
  4704.  *
  4705.  * X CLIPBOARD ('+')
  4706.  *
  4707.  * Text selection stuff that uses the GUI clipboard register '+'.
  4708.  * Under X, this matches the standard cut/paste buffer CLIPBOARD selection.
  4709.  * It will be used for unnamed cut/pasting is 'clipboard' contains "unnamed",
  4710.  * otherwise you will need to do <"+p>. "
  4711.  * If not under X, it is synonymous with the selection register '*'.
  4712.  */
  4713.  
  4714. /*
  4715.  * Routine to export any final X selection we had to the environment
  4716.  * so that the text is still available after vim has exited. X selections
  4717.  * only exist while the owning application exists, so we write to the
  4718.  * permanent (while X runs) store CUT_BUFFER0.
  4719.  * Dump the CLIPBOARD selection if we own it (it's logically the more
  4720.  * 'permanent' of the two), otherwise the PRIMARY one.
  4721.  * For now, use a hard-coded sanity limit of 1Mb of data.
  4722.  */
  4723. #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
  4724.     void
  4725. x11_export_final_selection()
  4726. {
  4727.     Display    *dpy;
  4728.     char_u    *str = NULL;
  4729.     long_u    len = 0;
  4730.     int        motion_type = -1;
  4731.  
  4732. # ifdef FEAT_GUI
  4733.     if (gui.in_use)
  4734.     dpy = gui.dpy;
  4735.     else
  4736. # endif
  4737. # ifdef FEAT_XCLIPBOARD
  4738.     dpy = xterm_dpy;
  4739. # else
  4740.     return;
  4741. # endif
  4742.  
  4743.     /* Get selection to export */
  4744.     if (clip_plus.owned)
  4745.     motion_type = clip_convert_selection(&str, &len, &clip_plus);
  4746.     else if (clip_star.owned)
  4747.     motion_type = clip_convert_selection(&str, &len, &clip_star);
  4748.  
  4749.     /* Check it's OK */
  4750.     if (dpy != NULL && str != NULL && motion_type >= 0
  4751.                            && len < 1024*1024 && len > 0)
  4752.     {
  4753.     XStoreBuffer(dpy, (char *)str, (int)len, 0);
  4754.     XFlush(dpy);
  4755.     }
  4756.  
  4757.     vim_free(str);
  4758. }
  4759. #endif
  4760.  
  4761.     void
  4762. clip_free_selection(cbd)
  4763.     VimClipboard    *cbd;
  4764. {
  4765.     struct yankreg *y_ptr = y_current;
  4766.  
  4767.     if (cbd == &clip_plus)
  4768.     y_current = &y_regs[PLUS_REGISTER];
  4769.     else
  4770.     y_current = &y_regs[STAR_REGISTER];
  4771.     free_yank_all();
  4772.     y_current->y_size = 0;
  4773.     y_current = y_ptr;
  4774. }
  4775.  
  4776. /*
  4777.  * Get the selected text and put it in the gui selection register '*' or '+'.
  4778.  */
  4779.     void
  4780. clip_get_selection(cbd)
  4781.     VimClipboard    *cbd;
  4782. {
  4783.     struct yankreg *old_y_previous, *old_y_current;
  4784.     pos_T    old_cursor;
  4785. #ifdef FEAT_VISUAL
  4786.     pos_T    old_visual;
  4787.     int        old_visual_mode;
  4788. #endif
  4789.     colnr_T    old_curswant;
  4790.     int        old_set_curswant;
  4791.     oparg_T    oa;
  4792.     cmdarg_T    ca;
  4793.  
  4794.     if (cbd->owned)
  4795.     {
  4796.     if ((cbd == &clip_plus && y_regs[PLUS_REGISTER].y_array != NULL)
  4797.         || (cbd == &clip_star && y_regs[STAR_REGISTER].y_array != NULL))
  4798.         return;
  4799.  
  4800.     /* Get the text between clip_star.start & clip_star.end */
  4801.     old_y_previous = y_previous;
  4802.     old_y_current = y_current;
  4803.     old_cursor = curwin->w_cursor;
  4804.     old_curswant = curwin->w_curswant;
  4805.     old_set_curswant = curwin->w_set_curswant;
  4806. #ifdef FEAT_VISUAL
  4807.     old_visual = VIsual;
  4808.     old_visual_mode = VIsual_mode;
  4809. #endif
  4810.     clear_oparg(&oa);
  4811.     oa.regname = (cbd == &clip_plus ? '+' : '*');
  4812.     oa.op_type = OP_YANK;
  4813.     vim_memset(&ca, 0, sizeof(ca));
  4814.     ca.oap = &oa;
  4815.     ca.cmdchar = 'y';
  4816.     ca.count1 = 1;
  4817.     ca.retval = CA_NO_ADJ_OP_END;
  4818.     do_pending_operator(&ca, 0, TRUE);
  4819.     y_previous = old_y_previous;
  4820.     y_current = old_y_current;
  4821.     curwin->w_cursor = old_cursor;
  4822.     curwin->w_curswant = old_curswant;
  4823.     curwin->w_set_curswant = old_set_curswant;
  4824. #ifdef FEAT_VISUAL
  4825.     VIsual = old_visual;
  4826.     VIsual_mode = old_visual_mode;
  4827. #endif
  4828.     }
  4829.     else
  4830.     {
  4831.     clip_free_selection(cbd);
  4832.  
  4833.     /* Try to get selected text from another window */
  4834.     clip_gen_request_selection(cbd);
  4835.     }
  4836. }
  4837.  
  4838. /* Convert from the GUI selection string into the '*'/'+' register */
  4839.     void
  4840. clip_yank_selection(type, str, len, cbd)
  4841.     int        type;
  4842.     char_u    *str;
  4843.     long    len;
  4844.     VimClipboard *cbd;
  4845. {
  4846.     struct yankreg *y_ptr;
  4847.  
  4848.     if (cbd == &clip_plus)
  4849.     y_ptr = &y_regs[PLUS_REGISTER];
  4850.     else
  4851.     y_ptr = &y_regs[STAR_REGISTER];
  4852.  
  4853.     clip_free_selection(cbd);
  4854.  
  4855.     str_to_reg(y_ptr, type, str, len);
  4856. }
  4857.  
  4858. /*
  4859.  * Convert the '*'/'*' register into a GUI selection string returned in *str
  4860.  * with length *len.
  4861.  * Returns the motion type, or -1 for failure.
  4862.  */
  4863.     int
  4864. clip_convert_selection(str, len, cbd)
  4865.     char_u    **str;
  4866.     long_u    *len;
  4867.     VimClipboard *cbd;
  4868. {
  4869.     char_u    *p;
  4870.     int        lnum;
  4871.     int        i, j;
  4872.     int_u    eolsize;
  4873.     struct yankreg *y_ptr;
  4874.  
  4875.     if (cbd == &clip_plus)
  4876.     y_ptr = &y_regs[PLUS_REGISTER];
  4877.     else
  4878.     y_ptr = &y_regs[STAR_REGISTER];
  4879.  
  4880. #ifdef USE_CRNL
  4881.     eolsize = 2;
  4882. #else
  4883.     eolsize = 1;
  4884. #endif
  4885.  
  4886.     *str = NULL;
  4887.     *len = 0;
  4888.     if (y_ptr->y_array == NULL)
  4889.     return -1;
  4890.  
  4891.     for (i = 0; i < y_ptr->y_size; i++)
  4892.     *len += (long_u)STRLEN(y_ptr->y_array[i]) + eolsize;
  4893.  
  4894.     /*
  4895.      * Don't want newline character at end of last line if we're in MCHAR mode.
  4896.      */
  4897.     if (y_ptr->y_type == MCHAR && *len > eolsize)
  4898.     *len -= eolsize;
  4899.  
  4900.     p = *str = lalloc(*len, TRUE);
  4901.     if (p == NULL)
  4902.     return -1;
  4903.     lnum = 0;
  4904.     for (i = 0, j = 0; i < (int)*len; i++, j++)
  4905.     {
  4906.     if (y_ptr->y_array[lnum][j] == '\n')
  4907.         p[i] = NUL;
  4908.     else if (y_ptr->y_array[lnum][j] == NUL)
  4909.     {
  4910. #ifdef USE_CRNL
  4911.         p[i++] = '\r';
  4912. #endif
  4913. #ifdef USE_CR
  4914.         p[i] = '\r';
  4915. #else
  4916.         p[i] = '\n';
  4917. #endif
  4918.         lnum++;
  4919.         j = -1;
  4920.     }
  4921.     else
  4922.         p[i] = y_ptr->y_array[lnum][j];
  4923.     }
  4924.     return y_ptr->y_type;
  4925. }
  4926.  
  4927. #endif /* FEAT_CLIPBOARD || PROTO */
  4928.  
  4929.  
  4930. #ifdef FEAT_EVAL
  4931. /*
  4932.  * Return the contents of a register as a single allocated string.
  4933.  * Used for "@r" in expressions.
  4934.  * Returns NULL for error.
  4935.  */
  4936.     char_u *
  4937. get_reg_contents(regname)
  4938.     int        regname;
  4939. {
  4940.     long    i;
  4941.     char_u  *retval;
  4942.     int        allocated;
  4943.     long    len;
  4944.  
  4945.     /* Don't allow using an expression register inside an expression */
  4946.     if (regname == '=')
  4947.     return NULL;
  4948.  
  4949.     if (regname == '@')        /* "@@" is used for unnamed register */
  4950.     regname = '"';
  4951.  
  4952.     /* check for valid regname */
  4953.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  4954.     return NULL;
  4955.  
  4956. #ifdef FEAT_CLIPBOARD
  4957.     if (regname == '*')
  4958.     {
  4959.     if (!clip_star.available)
  4960.         regname = 0;
  4961.     else
  4962.         clip_get_selection(&clip_star);    /* may fill * register */
  4963.     }
  4964.     else if (regname == '+')
  4965.     {
  4966.     if (!clip_plus.available)
  4967.         regname = 0;
  4968.     else
  4969.         clip_get_selection(&clip_plus);    /* may fill + register */
  4970.     }
  4971. #endif
  4972.  
  4973.     if (get_spec_reg(regname, &retval, &allocated, FALSE))
  4974.     {
  4975.     if (retval == NULL)
  4976.         return NULL;
  4977.     if (!allocated)
  4978.         retval = vim_strsave(retval);
  4979.     return retval;
  4980.     }
  4981.  
  4982.     get_yank_register(regname, FALSE);
  4983.     if (y_current->y_array == NULL)
  4984.     return NULL;
  4985.  
  4986.     /*
  4987.      * Compute length of resulting string.
  4988.      */
  4989.     len = 0;
  4990.     for (i = 0; i < y_current->y_size; ++i)
  4991.     {
  4992.     len += (long)STRLEN(y_current->y_array[i]);
  4993.     /*
  4994.      * Insert a newline between lines and after last line if
  4995.      * y_type is MLINE.
  4996.      */
  4997.     if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  4998.         ++len;
  4999.     }
  5000.  
  5001.     retval = lalloc(len + 1, TRUE);
  5002.  
  5003.     /*
  5004.      * Copy the lines of the yank register into the string.
  5005.      */
  5006.     if (retval != NULL)
  5007.     {
  5008.     len = 0;
  5009.     for (i = 0; i < y_current->y_size; ++i)
  5010.     {
  5011.         STRCPY(retval + len, y_current->y_array[i]);
  5012.         len += (long)STRLEN(retval + len);
  5013.  
  5014.         /*
  5015.          * Insert a NL between lines and after the last line if y_type is
  5016.          * MLINE.
  5017.          */
  5018.         if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  5019.         retval[len++] = '\n';
  5020.     }
  5021.     retval[len] = NUL;
  5022.     }
  5023.  
  5024.     return retval;
  5025. }
  5026.  
  5027. /*
  5028.  * Store string "str" in register "name".
  5029.  * If "must_append" is TRUE, always append to the register.  Otherwise append
  5030.  * if "name" is an uppercase letter.
  5031.  * Careful: 'str' is modified, you may have to use a copy!
  5032.  * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
  5033.  */
  5034.     void
  5035. write_reg_contents(name, str, must_append)
  5036.     int        name;
  5037.     char_u    *str;
  5038.     int        must_append;
  5039. {
  5040.     struct yankreg  *old_y_previous, *old_y_current;
  5041.     long        len;
  5042.  
  5043.     /* Special case: '/' search pattern */
  5044.     if (name == '/')
  5045.     {
  5046.     set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
  5047.     return;
  5048.     }
  5049.  
  5050.     if (!valid_yank_reg(name, TRUE))        /* check for valid reg name */
  5051.     {
  5052.     EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
  5053.     return;
  5054.     }
  5055.  
  5056.     if (name == '_')        /* black hole: nothing to do */
  5057.     return;
  5058.  
  5059.     /* Don't want to change the current (unnamed) register */
  5060.     old_y_previous = y_previous;
  5061.     old_y_current = y_current;
  5062.  
  5063.     get_yank_register(name, TRUE);
  5064.     if (!y_append && !must_append)
  5065.     free_yank_all();
  5066.     len = (long)STRLEN(str);
  5067.     str_to_reg(y_current,
  5068.         (len > 0 && (str[len - 1] == '\n' || str[len -1] == '\r'))
  5069.          ? MLINE : MCHAR, str, len);
  5070.  
  5071. #ifdef FEAT_CLIPBOARD
  5072.     /*
  5073.      * If we are writing to the selection register, send result to selection.
  5074.      */
  5075.     if (y_current == &(y_regs[STAR_REGISTER]) && clip_star.available)
  5076.     {
  5077.     clip_own_selection(&clip_star);
  5078.     clip_gen_set_selection(&clip_star);
  5079.     }
  5080.     /*
  5081.      * If we are writing to the clipboard register, send result to clipboard.
  5082.      */
  5083.     else if (y_current == &(y_regs[PLUS_REGISTER]) && clip_plus.available)
  5084.     {
  5085.     clip_own_selection(&clip_plus);
  5086.     clip_gen_set_selection(&clip_plus);
  5087.     }
  5088. #endif
  5089.  
  5090.     /* ':let @" = "val"' should change the meaning of the "" register */
  5091.     if (name != '"')
  5092.     y_previous = old_y_previous;
  5093.     y_current = old_y_current;
  5094. }
  5095. #endif    /* FEAT_EVAL */
  5096.  
  5097. #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
  5098. /*
  5099.  * Put a string into a register.  When the register is not empty, the string
  5100.  * is appended.
  5101.  */
  5102.     static void
  5103. str_to_reg(y_ptr, type, str, len)
  5104.     struct yankreg    *y_ptr;        /* pointer to yank register */
  5105.     int            type;        /* MCHAR or MLINE */
  5106.     char_u        *str;        /* string to put in register */
  5107.     long        len;        /* lenght of string */
  5108. {
  5109.     int        lnum;
  5110.     long    start;
  5111.     long    i;
  5112.     int        extra;
  5113.     int        newlines;        /* number of lines added */
  5114.     int        extraline = 0;        /* extra line at the end */
  5115.     int        append = FALSE;        /* append to last line in register */
  5116.     char_u    *s;
  5117.     char_u    **pp;
  5118.  
  5119.     if (y_ptr->y_array == NULL)        /* NULL means emtpy register */
  5120.     y_ptr->y_size = 0;
  5121.  
  5122.     /*
  5123.      * Count the number of lines within the string
  5124.      */
  5125.     newlines = 0;
  5126.     for (i = 0; i < len; i++)
  5127.     if (str[i] == '\n')
  5128.         ++newlines;
  5129.     if (type == MCHAR || len == 0 || str[len - 1] != '\n')
  5130.     {
  5131.     extraline = 1;
  5132.     ++newlines;    /* count extra newline at the end */
  5133.     }
  5134.     if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
  5135.     {
  5136.     append = TRUE;
  5137.     --newlines;    /* uncount newline when appending first line */
  5138.     }
  5139.  
  5140.     /*
  5141.      * Allocate an array to hold the pointers to the new register lines.
  5142.      * If the register was not empty, move the existing lines to the new array.
  5143.      */
  5144.     pp = (char_u **)lalloc_clear((y_ptr->y_size + newlines)
  5145.                             * sizeof(char_u *), TRUE);
  5146.     if (pp == NULL)    /* out of memory */
  5147.     return;
  5148.     for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
  5149.     pp[lnum] = y_ptr->y_array[lnum];
  5150.     vim_free(y_ptr->y_array);
  5151.     y_ptr->y_array = pp;
  5152.  
  5153.     /*
  5154.      * Find the end of each line and save it into the array.
  5155.      */
  5156.     for (start = 0; start < len + extraline; start += i + 1)
  5157.     {
  5158.     for (i = start; i < len; ++i)    /* find the end of the line */
  5159.         if (str[i] == '\n')
  5160.         break;
  5161.     i -= start;            /* i is now length of line */
  5162.     if (append)
  5163.     {
  5164.         --lnum;
  5165.         extra = (int)STRLEN(y_ptr->y_array[lnum]);
  5166.     }
  5167.     else
  5168.         extra = 0;
  5169.     s = alloc((unsigned)(i + extra + 1));
  5170.     if (s == NULL)
  5171.         break;
  5172.     if (extra)
  5173.     {
  5174.         mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
  5175.         vim_free(y_ptr->y_array[lnum]);
  5176.     }
  5177.     if (i)
  5178.         mch_memmove(s + extra, str + start, (size_t)i);
  5179.     extra += i;
  5180.     s[extra] = NUL;
  5181.     y_ptr->y_array[lnum++] = s;
  5182.     while (--extra >= 0)
  5183.     {
  5184.         if (*s == NUL)
  5185.         *s = '\n';        /* replace NUL with newline */
  5186.         ++s;
  5187.     }
  5188.     append = FALSE;            /* only first line is appended */
  5189.     }
  5190.     y_ptr->y_type = type;
  5191.     y_ptr->y_size = lnum;
  5192.     y_ptr->y_width = 0;
  5193. }
  5194. #endif /* FEAT_CLIPBOARD || FEAT_EVAL || PROTO */
  5195.  
  5196.     void
  5197. clear_oparg(oap)
  5198.     oparg_T    *oap;
  5199. {
  5200.     vim_memset(oap, 0, sizeof(oparg_T));
  5201. }
  5202.  
  5203. static long    line_count_info __ARGS((char_u *line, long *wc, long limit, int eol_size));
  5204.  
  5205. /*
  5206.  *  Count the number of characters and "words" in a line.
  5207.  *
  5208.  *  "Words" are counted by looking for boundaries between non-space and
  5209.  *  space characters.  (it seems to produce results that match 'wc'.)
  5210.  *
  5211.  *  Return value is character count; word count for the line is ADDED
  5212.  *  to "*wc".
  5213.  *
  5214.  *  The function will only examine the first "limit" characters in the
  5215.  *  line, stopping if it encounters an end-of-line (NUL byte).  In that
  5216.  *  case, eol_size will be added to the character count to account for
  5217.  *  the size of the EOL character.
  5218.  */
  5219.     static long
  5220. line_count_info(line, wc, limit, eol_size)
  5221.     char_u    *line;
  5222.     long    *wc;
  5223.     long    limit;
  5224.     int        eol_size;
  5225. {
  5226.     long    i, words = 0;
  5227.     int        is_word = 0;
  5228.  
  5229.     for (i = 0; line[i] && i < limit; i++)
  5230.     {
  5231.     if (is_word)
  5232.     {
  5233.         if (vim_isspace(line[i]))
  5234.         {
  5235.         words++;
  5236.         is_word = 0;
  5237.         }
  5238.     }
  5239.     else if (!vim_isspace(line[i]))
  5240.         is_word = 1;
  5241.     }
  5242.  
  5243.     if (is_word)
  5244.     words++;
  5245.     *wc += words;
  5246.  
  5247.     /* Add eol_size if the end of line was reached before hitting limit. */
  5248.     if (!line[i] && i < limit)
  5249.     i += eol_size;
  5250.     return i;
  5251. }
  5252.  
  5253. /*
  5254.  * Give some info about the position of the cursor (for "g CTRL-G").
  5255.  * In Visual mode, give some info about the selected region.  (In this case,
  5256.  * the *_count_cursor variables store running totals for the selection.)
  5257.  */
  5258.     void
  5259. cursor_pos_info()
  5260. {
  5261.     char_u    *p;
  5262.     char_u    buf1[20];
  5263.     char_u    buf2[20];
  5264.     linenr_T    lnum;
  5265.     long    char_count = 0;
  5266.     long    char_count_cursor = 0;
  5267.     int        eol_size;
  5268.     long    last_check = 100000L;
  5269.     long    word_count = 0;
  5270.     long    word_count_cursor = 0;
  5271. #ifdef FEAT_VISUAL
  5272.     long    line_count_selected = 0;
  5273.     pos_T    min_pos, max_pos;
  5274.     oparg_T    oparg;
  5275.     struct block_def    bd;
  5276. #endif
  5277.  
  5278.     /*
  5279.      * Compute the length of the file in characters.
  5280.      */
  5281.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  5282.     {
  5283.     MSG(_(no_lines_msg));
  5284.     }
  5285.     else
  5286.     {
  5287.     if (get_fileformat(curbuf) == EOL_DOS)
  5288.         eol_size = 2;
  5289.     else
  5290.         eol_size = 1;
  5291.  
  5292. #ifdef FEAT_VISUAL
  5293.     if (VIsual_active)
  5294.     {
  5295.         if (lt(VIsual, curwin->w_cursor))
  5296.         {
  5297.         min_pos = VIsual;
  5298.         max_pos = curwin->w_cursor;
  5299.         }
  5300.         else
  5301.         {
  5302.         min_pos = curwin->w_cursor;
  5303.         max_pos = VIsual;
  5304.         }
  5305.         if (VIsual_mode == Ctrl_V)
  5306.         {
  5307.         oparg.is_VIsual = 1;
  5308.         oparg.block_mode = 1;
  5309.         oparg.op_type = OP_NOP;
  5310.         getvcols(curwin, &min_pos, &max_pos,
  5311.             &oparg.start_vcol, &oparg.end_vcol);
  5312.         /* Swap the start, end vcol if needed */
  5313.         if (oparg.end_vcol < oparg.start_vcol)
  5314.         {
  5315.             oparg.end_vcol += oparg.start_vcol;
  5316.             oparg.start_vcol = oparg.end_vcol - oparg.start_vcol;
  5317.             oparg.end_vcol -= oparg.start_vcol;
  5318.         }
  5319.         }
  5320.         line_count_selected = max_pos.lnum - min_pos.lnum + 1;
  5321.     }
  5322. #endif
  5323.  
  5324.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  5325.     {
  5326.         /* Check for a CTRL-C every 100000 characters. */
  5327.         if (char_count > last_check)
  5328.         {
  5329.         ui_breakcheck();
  5330.         if (got_int)
  5331.             return;
  5332.         last_check = char_count + 100000L;
  5333.         }
  5334.  
  5335. #ifdef FEAT_VISUAL
  5336.         /* Do extra processing for VIsual mode. */
  5337.         if (VIsual_active
  5338.             && lnum >= min_pos.lnum && lnum <= max_pos.lnum)
  5339.         {
  5340.         switch (VIsual_mode)
  5341.         {
  5342.             case Ctrl_V:
  5343.             block_prep(&oparg, &bd, lnum, 0);
  5344.             char_count_cursor += line_count_info(bd.textstart,
  5345.                 &word_count_cursor, (long)bd.textlen, eol_size);
  5346.             break;
  5347.             case 'V':
  5348.             char_count_cursor += line_count_info(ml_get(lnum),
  5349.                 &word_count_cursor, (long)MAXCOL, eol_size);
  5350.             break;
  5351.             case 'v':
  5352.             {
  5353.                 colnr_T start_col = (lnum == min_pos.lnum)
  5354.                                ? min_pos.col : 0;
  5355.                 colnr_T end_col = (lnum == max_pos.lnum)
  5356.                       ? max_pos.col - start_col + 1 : MAXCOL;
  5357.  
  5358.                 char_count_cursor +=
  5359.                 line_count_info(ml_get(lnum) + start_col,
  5360.                  &word_count_cursor, (long)end_col, eol_size);
  5361.             }
  5362.             break;
  5363.         }
  5364.         }
  5365.         else
  5366. #endif
  5367.         {
  5368.         /* In non-visual mode, check for the line the cursor is on */
  5369.         if (lnum == curwin->w_cursor.lnum)
  5370.         {
  5371.             word_count_cursor += word_count;
  5372.             char_count_cursor = char_count +
  5373.             line_count_info(ml_get(lnum), &word_count_cursor,
  5374.                   (long)(curwin->w_cursor.col + 1), eol_size);
  5375.         }
  5376.         }
  5377.         /* Add to the running totals */
  5378.         char_count += line_count_info(ml_get(lnum), &word_count,
  5379.                               (long)MAXCOL, eol_size);
  5380.     }
  5381.  
  5382.     /* Correction for when last line doesn't have an EOL. */
  5383.     if (!curbuf->b_p_eol && curbuf->b_p_bin)
  5384.         char_count -= eol_size;
  5385.  
  5386. #ifdef FEAT_VISUAL
  5387.     if (VIsual_active)
  5388.     {
  5389.         if (VIsual_mode == Ctrl_V)
  5390.         {
  5391.         getvcols(curwin, &min_pos, &max_pos, &min_pos.col,
  5392.             &max_pos.col);
  5393.         sprintf((char *)buf1, _("%ld Cols; "),
  5394.             (long)(oparg.end_vcol - oparg.start_vcol + 1));
  5395.         }
  5396.         else
  5397.         buf1[0] = NUL;
  5398.  
  5399.         sprintf((char *)IObuff,
  5400.         _("Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"),
  5401.             buf1, line_count_selected,
  5402.             (long)curbuf->b_ml.ml_line_count,
  5403.             word_count_cursor, word_count,
  5404.             char_count_cursor, char_count);
  5405.     }
  5406.     else
  5407. #endif
  5408.     {
  5409.         p = ml_get_curline();
  5410.         validate_virtcol();
  5411.         col_print(buf1, (int)curwin->w_cursor.col + 1,
  5412.             (int)curwin->w_virtcol + 1);
  5413.         col_print(buf2, (int)STRLEN(p), linetabsize(p));
  5414.  
  5415.         sprintf((char *)IObuff,
  5416.         _("Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"),
  5417.             (char *)buf1, (char *)buf2,
  5418.             (long)curwin->w_cursor.lnum,
  5419.             (long)curbuf->b_ml.ml_line_count,
  5420.             word_count_cursor, word_count,
  5421.             char_count_cursor, char_count);
  5422.     }
  5423.  
  5424. #ifdef FEAT_MBYTE
  5425.     char_count = bomb_size();
  5426.     if (char_count > 0)
  5427.         sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"),
  5428.                                   char_count);
  5429. #endif
  5430.     /* Don't shorten this message, the user asked for it. */
  5431.     p = p_shm;
  5432.     p_shm = (char_u *)"";
  5433.     msg(IObuff);
  5434.     p_shm = p;
  5435.     }
  5436. }
  5437.